Good morning James,
At 09:14 18/06/2001 +0100, James Strachan wrote:
>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.
Thanks - I'd looked at these, but the syntax grew messy enough that I
preferred the verbose but straightforward code, with intermediate
variables. E.g:
DocumentHelper dh = new DocumentHelper();
dh.createAttribute (dh.createElement ("complexType"), "mixed", "true");
Once you start with nested elements the syntax gets pretty opaque - largely
because it's "bottom up", you do the innermost widget first.
>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.
Not my idea :) -- I've seen it in a number of places before... most
recently JDOM (ducks to avoid missile :)
>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" );
Sounds useful, I'd suggest it applies to all setXXX methods? Unless you can
see a reason for not keeping it consistent?
> > 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.
Great. Could break existing code, but simple enough to fix.
> > 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 );
Lovely - the getRootElement() of a newly created doc is what I hadn't
thought of. Would the fragment be created in NO_NAMESPACE, so that when you
add it to someOtherElement it inherits someOtherElement's namespace?
>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).
Thanks very much. I'm trying to avoid CVS access at present (need to either
use WinCVS in Unix-mode, or get Linux ISDN and proxy servers working) so
I'll grab a snapshot in the next couple of days.
> > 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.
Yup, I get the idea now; thanks.
>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
Best Regards,
Thomas.
_______________________________________________
dom4j-dev mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/dom4j-dev