Hi Thomas
There are some helper methods already that might help. For example
Element foo = DocumentHelper.createElement( "foo" );
Element price = foo.addElement( "price" );
price.setAttributeValue( "amount", "10" );
price.setAttributeValue( "currency", "GBP" );
Note that none of the above requires an explicit "new" operation.
So the "addElement" method already returns a reference to the new element
thats just been created.
More comments below...
From: "Thomas Nichols" <[EMAIL PROTECTED]>
> Please could someone explain the rationale behind having (e.g.)
Element.add
> (Attribute) return void, rather than a reference to self? This precludes
> chaining of add()s --
> Element newEl = (new DefaultElement ("price")).add (new DefaultAttribute
> ("currency", "GBP")).add (new DefaultAttribute ("amount", "10"));
>
> This is considerably more succinct than the current code, where the adds
> must be separated: either
> 1.
> Element newEl = (new DefaultElement ("price")).add (new DefaultAttribute
> ("currency", "GBP"));
> newEl.add (new DefaultAttribute ("amount", "10"));
>
> // Yuk - orthogonality out of the window
>
> or 2.
> Element newEl = (new DefaultElement ("price"));
> newEl.add (new DefaultAttribute ("currency", "GBP"));
> newEl.add (new DefaultAttribute ("amount", "10"));
> // Tidy but verbose.
>
> This could also affect the syntax of the existing addText() and addCDATA()
> - both take a String and return void, they could perhaps return self
> (Element) instead?
Agreed. I originally had the addText() , addCDATA(), addComment() to return
the new node that was added (Text, CDATA or Comment) but then thought that
this would restrict possible optimisations which may avoid creating a Text
object until when absolutely necessary (i.e. lazily). So I made the
addText(), addCDATA(), addComment() methods void.
Though I like your idea of returning the Element such that these methods
could be
chained.
Element foo = ...;
foo.addText( "hello" ).addCDATA( "< > &" ).addEntity( "amp" );
What do you think of the idea of setAttributeValue() returning a reference
to the element so that they could be nested too?
Element foo = ...;
foo.setAttributeValue( "amount", "10" ).setAttributeValue( "currency",
"GBP" );
> Only addEntity() seems non-orthogonal - this takes a String and returns
> _Entity_, a reference to the Entity object just created.
Agreed. I think that addEntity() should return a reference to the Element.
> I actually want to insert hard-coded XML fragments into an existing
> document, and it's becoming very long-winded. I'd be happiest to do
> String xmlFragment = "<complexType mixed = 'true'> <sequence> <element
> ref='xyz' /> </sequence> </complexType>";
> Element newEl = parser.parse (xmlFragment);
> parentEl.add (newEl);
Maybe a helper method might help here. Consider the following:-
String xmlFragment = "<complexType mixed = 'true'> <sequence> <element
ref='xyz' /> </sequence> </complexType>";
Document document = DocumentHelper.parseText( xmlFragment )
Then if you wanted to use the <complexType> element in some other document
the following code could be used...
String xmlFragment = "<complexType mixed = 'true'> <sequence> <element
ref='xyz' /> </sequence> </complexType>";
Document document = DocumentHelper.parseText( xmlFragment )
Element complexType = document.getRootElement();
complexType.detach();
someOtherElement.add( complexType );
I've added the DocumentHelper.parseText( xmlText ) helper method to the
current CVS image along with a JUnit test case to ensure it works
(org.dom4j.TestParseText). So you could try using the current CVS image or a
daily build and see if this new method helps. (It is a pretty trivial helper
method though).
> I need to have namespaces behaving sensibly, so that element xyz inherits
> the namespace of parentEl, etc. Is there any way to do this?
To handle namespaces you can use both the Namespace class and the QName
class which are both instances of the flyweight design pattern.
The Namespace flyweight object represents a particular namespace URI and
prefix. The QName object represents a local name and a Namespace (and hence
a fully qualified name).
So if you wanted to add <my:foo> and <my:bar> elements to some root element
you could do ti using the following code. Note that the explicit use of
Namespace is optional, just using the QName class will do.
public class Foo {
// namespace for QNames
public static final Namespace MY_NS = Namespace.get( "my",
"http://foo.com" );
// QNames...
public static final QName FOO_QNAME = QName.get( "foo", MY_NS );
public static final QName BAR_QNAME = QName.get( "bar", MY_NS );
public static final QName XYZ_QNAME = QName.get( "something:xyz",
"http://xyz.com/foobar" );
public void doSomething() {
Element root = DocumentHelper.createElement( "root" );
Element foo = root.addElement( FOO_QNAME );
Element bar = foo.addElement( BAR_QNAME );
...
// lookup the <my:foo> element...
Element aFoo = root.element( FOO_QNAME );
}
> Can I use
> SAXReader.read() to parse fragments? I haven't yet managed to get this to
> work, so I'm manually creating DefaultElements and DefaultAttributes and
> chaining them together.
SAXReader.read() can only parse complete documents. To be able to parse a
fragment I'd just wrap your fragment in a single tag and parse it as a valid
XML document then just remove the content of the root element.
e.g.
// parse a fragment
String fragment = "<fragment> <a/> <b/> <c/> </fragment>";
Document fragDoc = DocumentHelper.parseText( fragment );
Element fragElement = fragDoc.getRootElement();
// now lets move the content of the fragment to a new destination
Element destination = ...;
for ( Iterator iter = fragElement.nodeIterator(); iter.hasNext(); ) {
Node node = (Node) iter.next();
node.detach();
destination.add( node );
}
> Thanks to all - I _like_ this library.
Great. Any comments or ideas are greatly appreciated.
James
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
_______________________________________________
dom4j-dev mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/dom4j-dev