Imagine that you want to parse some XML for creating some buisness
objects. Let's assume that both have their own untouchable structure.
The buisness objects would look like this (I use only 1 class for the
example) :
public class Module {
// private declarations omitted here...
public Module( String id ) { /* ... */ }
public String getID() { /* ... */ }
public void addModule( Module subModule ) { /* ... */ }
public Module[] getSubModules() { /* ... */ }
}
You see the idea of recursive composition.
Now we've got some XML like this :
<module id="1">
<module id="1.1" />
<module id="1.2">
<module id="1.2.1" />
<module id="1.2.2" />
</module>
</module>
Relative paths for ElementHandler would allow to write a simple handler,
no matter how the element structure goes deep. But how will your code
know to which parent the current Module should be attached ? A class
variable cannot be seen as a correct solution. The answer will be some
kind of context-passing.
The first idea that came to my mind is to modify the ElementHandler like
this :
public interface ElementHandler {
void onStart( ElementPath path, Object context ) ;
void onEnd( ElementPath path, Object context ) ;
}
This is not serious, at least for compatibility with existing
application code. And context-passing is not always required, so it
shouldn't pollute the API.
I noticed that the ElementPath interface could be slightly modified
without a great impact (it is only implemented by ElementStack for now).
The following methods could be added :
public interface ElementStack {
// ...
Object getCurrentContext() ;
void setCurrentContext( Object context ) ;
}
The getCurrentContext() methods returns the current context object in
the stack. The setCurrentContext( Object ) method sets the context
object in the stack. "Stack" here means "the stack of Element nestings".
Each entry of this stack would have a additional slot for a reference to
a context objects. The default value of a context object is the value of
the context object in the stack entry just below.
After the parsing is done (and the buisness objects are constructed),
the application may need to retrieve a reference to a "root" of the
buisness objects. This would require the SAXReader to handle context
retrieving, this could be done by adding the following method :
Object getRootContext() ;
It returns the value is the context object at the lowest level of the
Element stack once the parsing is done.
And this is how the example gets implements :
PatternHandler ph = new PatternHandler() ;
ph.add(
"/module",
new ElementHandler() {
public void onStart( ElementPath ep ) {
Module rootModule = new Module(
ep.getCurrentAttribute( "id" ) ;
)
ep.setCurrentContext( rootModule ) ;
}
public void onEnd( ElementPath ep ) { }
}
) ;
ph.add(
"module",
new ElementHandler() {
public void onStart( ElementPath ep ) {
Module module = new Module(
ep.getCurrentAttribute( "id" ) ;
)
Module parent = ( Module ) ep.getContext() ;
parent.add( module ) ;
}
public void onEnd( ElementPath ep ) { }
}
) ;
reader.setDefaultHandler( ph ) ;
reader.read( input ) // standard parsing ;
Module rootModule = ( Module ) reader.getRootContext() ;
_______________________________________________
dom4j-dev mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/dom4j-dev