How to programmatically add a CDATA section to an XML document (with the internal Xerces) startup 594127 1280

How to programmatically add a CDATA section to an XML document (with the internal Xerces)

This problem probably sounds very easy and it is actually very easy, but it took me so long to figure this out I think it’s worth a blog. I’ll also explain how to generate and output xml documents with Xerces (bundled with Java)

While working on a project with Oracle MapViewer I was doing some testing to improve the performance of the map generating. One of my ideas was to use the map request xml api. With Oracle MapViewer you can send an xml document to the MapViewer server and receive an image or an xml document (with a url to the image in it). I usually use JDOM (www.jdom.org) to generate xml, but this time I was wondering why Sun hasn’t provided something like JDOM for us. I found a package called com.sun.org.apache.xerces.internal and it looked easy.

 

The first step is to setup the document

DocumentBuilderFactory dbf = new DocumentBuilderFactoryImpl();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();

Be sure to include right imports (from the package com.sun.org.apache.xerces.internal.* and com.sun.org.apache.xml.internal.*), otherwise you could end up with Xerces from another library. Because Xerces is used in many project this could also happen to you.

Now we can add the root element to the document

Element mapRequest = document.createElement("map_request");
mapRequest.setAttribute("datasource", "mvdemo");
mapRequest.setAttribute("basemap", "world_map");
mapRequest.setAttribute("format", "png_stream");
mapRequest.setAttribute("srid", "8307");
document.appendChild(mapRequest);

This is part of the map request I’m making, it probably won’t work because I omitted some details. This all was pretty easy, the next step also is very easy, but it took me a while to find a solution.
In the xml request I had to include a sql query to give a color to some of the polygons rendered on the map. The query looks like this:
select g.polygons from goad_map g where g.size>10

When you insert this in a text node of xml your xml is invalid because of the greater than sign. There are two solutions, the first is just adding a String to your xml and the > sign is automatically escaped.

Text text=document.createTextNode(“select g.polygons from goad_map g where g.size>10”);
mapRequest.appendChild(text);

When we look into the xml (I’ll explain how to do that later on) our query looks like this
>select g.polygons from goad_map g where g.size>0>With larger queries this will become pretty unreadable very soon.

This brings us to the second solution, using a CDATA tag. Just adding it with some glances at the javadoc didn’t work this time. So Google might help me out. But after a lot of keywords I still couldn’t find it. Maybe the AMIS library. We have quite some good books about xml, but none of them mentioned adding CDATA. A colleague mentioned Google code search (http://www.google.com/codesearch) a while ago, so I might give that a shot, I found out I wanted a CDATASection object. GCS came up with this result:

public CDATASection newCDATASection(Document document, String data) {
    return new CDATASectionImpl((DocumentImpl) document, data);
}

I still think it’s strange to cast to a DocumentImpl, but now I have the CDATA section I wanted.

The last step is to print the xml with indentation. First create a formatter

OutputFormat format = new OutputFormat(document);
format.setIndenting(true);

And finally print it to the preferred output

XMLSerializer serializer = new XMLSerializer(System.out, format);
serializer.serialize(document);

Hopefully this article will have a good rating in Google so other people won’t have to search so long for a very simple problem. Also have a look at Google code search (http://www.google.com/codesearch), it might save you a lot of time.