4

I find myself writing the same verbose DOM manipulation code again and again:

Element e1 = document.createElement("some-name");
e1.setAttribute("attr1", "val1");
e2.setAttribute("attr2", "val2");
document.appendChild(e1);

Element e2 = document.createElement("some-other-name");
e.appendChild(e2);

// Etc, the same for attributes and finding the nodes again:
Element e3 = (Element) document.getElementsByTagName("some-other-name").item(0);

Now, I don't want to switch architecture all together, i.e. I don't want to use JDOM, JAXB, or anything else. Just Java's org.w3c.dom. The reasons for this are

  1. It's about an old and big legacy system
  2. The XML is used in many places and XSLT transformed several times to get XML, HTML, PDF output
  3. I'm just looking for convenience, not a big change.

I'm just wondering if there is a nice wrapper library (e.g. with apache commons or google) that allows me to do things like this with a fluent style similar to jRTF:

// create a wrapper around my DOM document and manipulate it:
// like in jRTF, this code would make use of static imports
dom(document).add(
  element("some-name")
    .attr("attr1", "val1")
    .attr("attr2", "val2")
    .add(element("some-other-name")),
  element("more-elements")
);

and then

Element e3 = dom(document).findOne("some-other-name");

The important requirement I have here is that I explicitly want to operate on a org.w3c.dom.Document that

  1. already exists
  2. is pretty big
  3. needs quite a bit of manipulation

So transforming the org.w3c.dom.Document into JDOM, dom4j, etc seems like a bad idea. Wrapping it with adapters is what I'd prefer.

If it doesn't exist, I might roll my own, as this jRTF syntax looks really nice! And for XML, it seems quite easy to implement, as there are only few node types. This could become as powerful as jquery from the fluent API perspective!

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • 1
    Dom4J does almost exactly this, but with it it's own DOM implementation. If you want to rebuild this functionality, go ahead, but I would use Dom4J if I were you. – Sean Patrick Floyd Aug 09 '11 at 12:23
  • @Sean, to me, dom4j looks as verbose as DOM itself. But maybe I'm missing the fluent API from the scarce documentation? Besides, I'd prefer if the library would actually operate on a `org.w3c.dom` structure, not create its own – Lukas Eder Aug 09 '11 at 12:26
  • I know you are writing off JAXB for some reason, it if you have or can create an XSD for your input files, it generates all the code for you unmarshal and marshal and gives you a nice real Java object model to work with. –  Aug 09 '11 at 14:20
  • @Jarrod: The reason is: There is no XSD, the XML can be arbitrarily complex, the data source is from a database, the tags are database columns, or transformations thereof, marshalling and unmarshalling would mean an extra transformation step for quite big documents, etc..., and I want to use XSLT, later on for processing, so standard DOM is probably the best choice, or maybe wrapping DOM... – Lukas Eder Aug 09 '11 at 14:27

3 Answers3

4

To elaborate my comment, Dom4J gets you pretty close to what you wanted:

final Document dom = DocumentHelper.createDocument().addElement("some-name")
        .addAttribute("attr1", "val1")
        .addAttribute("attr2", "val2")
        .addElement("some-other-name").getDocument();
System.out.println(dom.asXML());

Output:

<?xml version="1.0" encoding="UTF-8"?>
<some-name attr1="val1" attr2="val2"><some-other-name/></some-name>

I know it's not native DOM, but it's very similar and it has very nice features for Java developers (element iterators, live element lists etc.)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • OK, that looks similar. But to elaborate my comment too... ;-) I don't want to create new documents, but operate on existing ones (and they're pretty big, so performance/memory is an issue here). So, I'm guessing, Dom4J doesn't allow for doing that? – Lukas Eder Aug 09 '11 at 12:46
  • @Lukas of course it allows you to manipulate existing documents, but I'm guessing the performance / memory requirements should be bad for huge documents. I have not used Dom4J with documents larger than a few hundred K, so I wouldn't know. – Sean Patrick Floyd Aug 09 '11 at 12:55
  • it does so by converting `org.w3c.dom.Document` into `org.dom4j.Document`, right? That's what I'd like to avoid... – Lukas Eder Aug 09 '11 at 13:00
  • @Lukas it allows you to modify existing *Dom4J* documents :-) – Sean Patrick Floyd Aug 09 '11 at 13:02
  • Just checked, it also allows you to import and export DOM documents, but it does not provide a live wrapper around them. – Sean Patrick Floyd Aug 09 '11 at 13:08
  • 1
    FYI, DOM4J has a significantly lower memory footprint compared to DOM (Xerces). – forty-two Aug 09 '11 at 14:36
  • @Per interesting, do you have any reference for that? – Sean Patrick Floyd Aug 09 '11 at 14:38
  • @Per, I'd be interested in a reference as well. I have [benchmarked Xerces, Xalan, and similar libraries](http://stackoverflow.com/questions/6340802/java-xpath-apache-jaxp-implementation-performance) before and I haven't found anything better than Xerces. Besides, I'm not sure whether XSLT (for rendering HTML, XML, and PDFs) is as performant or even feasible with DOM4J... Note, this is about a 10-year old legacy system. I'm not going to switch architecture anyway, just for a little convenience... – Lukas Eder Aug 09 '11 at 14:45
4

I found some tools that roughly do what I asked for in my question:

However, in the mean time, I am more inclinded to roll my own. I'm really a big fan of jquery, and I think jquery can be mapped to a Java fluent API:

http://www.jooq.org/products/jOOX

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • I have a similar project but its only for streaming output (consequently its extremely memory friendly as it doesn't load the whole DOM) See [**JATL**](http://code.google.com/p/jatl/). – Adam Gent Aug 28 '12 at 15:21
1

Well, this is maybe silly but why don't you implement that little API on your own? I'm sure you know DOM API pretty well and it won't take much time to implement what you want.

Btw consider using XPath for manipulation with document (you can also implement your mini-api over this one).

dxxx
  • 211
  • 1
  • 3
  • 9
  • Thanks for your hints. As I said, I'm going to roll my own if this doesn't exist yet. About using XPath instead of DOM, read my [previous question about XPath performance](http://stackoverflow.com/questions/6340802/java-xpath-apache-jaxp-implementation-performance). XPath should be prevented if possible, for performance reasons. – Lukas Eder Aug 09 '11 at 13:58
  • Yes, I also noticted performance issues of XPath and I'm mostly using direct DOM manipulation as you wrote before. Anyway it happens to me very often that I implement my own mini-api while using any "standard" API, because it mostly does not fit to me. – dxxx Aug 09 '11 at 14:07
  • Why not, if you give me your email or any contact:-) – dxxx Aug 11 '11 at 06:52
  • I'm almost done with a basic port of jquery to Java: http://code.google.com/p/joox/. There's also a user group there, where you can contact me, if you'd like to contribute! – Lukas Eder Aug 11 '11 at 09:21