Every XML element is passed to the doElement method in the Listener interface but, in many applications, it will be more convenient to pass each element directly to its own handler. This can be done by using the doElement method to invoke an ElementMapper.
When an ElementMapper encounters an element name for the first time, it uses Java reflection to find the appropriate handler and map the element name to that handler. The map is used to invoke the handler each time an element with that name is encountered.
SimpleElementMapper maps all element names to element handler methods in a single class, using the prefixed name (concatenation of prefix and local name) as the element name.
A Listener that uses a SimpleElementMapper might look like this:
public class MyListener extends AbstractErrorListener<Parser<Global>> { private ElementMapper<Parser<Global>> elementMapper; public MyListener() throws NoSuchMethodException, IllegalAccessException { // prefix "element_ to elment name to get method name // All methods are in this instance // name of default method is "defaultElement" elementMapper = new SimpleElementMapper<Parser<Global>>( "element_", this, "defaultElement"); } // receive each element from parser and send to appropriate method public void doElement(Parser<Global> parser, CurrentElement element) throws ListenerException, IOException { elementMapper.doElement(parser, element); } // method used when ElementMapper does not find a method public void defaultElement (Parser<Global> parser, CurrentElement element) throws ListenerException, IOException { element.parseContent(); } // handler for a method named "title" public void element_title(Parser<Global> parser, CurrentElement element) throws ListenerException, IOException { // do whatever we do at the beginning of a title element element.parseContent(); // do whatever we do at the end of a title element } }
ClassNamespaceElementMapper is not yet implemented.
ClassNamespaceElementMapper maps each namespace to a class, and each local name in that namespace to a method in the class that represents the namespace.
PackageNamespaceElementMapper maps each namespace to a package, and each local name in that namespace to a class in the package that represents the namespace.
PackageNamespaceElementMapper requires a NamespaceEntry for each namespace. The NamespaceEntry declares a namespace URI, a package name, a default element handler for the package, and the prefix that is added to each element name to get the class name of the corresponding element handler:
PackageNamespaceElementMapper.NamespaceEntry[] namespaceEntry; namespaceEntry[0] = new PackageNamespaceElementMapper.NamespaceEntry( namespaceUri, packageName, defaultHandlerForPackage, classNamePrefix); Listener myListener = new MyListener(unMappedElementHandler, namespaceEntry); public class MyListener extends AbstractErrorListener<Parser<Docbook>> { private ElementMapper elementMapper; public MyListener(ElementListener<Global> unmappedElementHandler, PackageNamespaceElementMapper .NamespaceEntry[] namespaceEntry) throws IOException { try { elementMapper = new PackageNamespaceElementMapper( unmappedElementHandler, namespaceEntry); } catch(PackageNamespaceElementMapper .DuplicateNamespaceException dx) { // shouldn't happen in a properly designed application throw new ListenerRuntimeException(dx); } } public void doElement(Parser<Docbook> parser, CurrentElement element) throws ListenerException, IOException { elementMapper.doElement(parser, element); } } // handler for a method named "title" in a namespace that maps to // package "foo" package foo; public class Element_title implements ElementListener<Parser<Global>> { public void doElement(Parser<Global> parser, CurrentElement element) throws ListenerException, IOException { // do whatever we do at the beginning of a title element element.parseContent(); // do whatever we do at the end of a title element } }