domcdatasaxonxerces

Strange behavior of Document createCDATASection method with Saxon (Maven Saxon-HE artifact 9.4)


I tried to use Saxon in place of JDK's default implementation (Xalan I guess) for XML transformation and Xpath. In my code I am creating a CDATA node using document.createCDATASection(data) method. Code looks as given below:

    CDATASection cdata = doc.createCDATASection("data");
    Node valueNode = node.appendChild(doc.createElement("value"));
    valueNode.appendChild(cdata);

Where node is some random node in my XML. It works fine with JDK's default implementation and resulting XML looks like:

            <node>
             <value><![CDATA[data]]></value>
            </node>

The same code starts behaving strange if I include Saxon maven artifact (Please note it is just inclusion and factory selection/instantiation is default, as it was earlier) and all the cdata nodes are treated as simple text nodes i.e. XML becomes:

            <node>
             <value>data</value>
            </node>

which on retrieval is causing issues as that code specifically checks for cdata elements which in later case has been removed. I am not sure why this is happening (looks like I have not used it correctly). I also tried excluding Xerces artifacts from my POM (transitive dependency for Saxon) but no luck. Also, verified that implementation classes for DocumentBuilderFactory etc are being used from JDK itself. Experts please help me if I am doing something wrong.

Thanks in advance.


Solution

  • I guess your application is probably doing a JAXP identity transformation from a DOMSource to a StreamResult in order to serialize the DOM. The Saxon implementation of the JAXP identity transformation uses the serialization rules of XSLT, which have the effect of dropping CDATA sections. This is perfectly conformant with JAXP, even if it isn't what the default JDK implementation does.

    If you are dependent on the behaviour of a particular implementation of the JAXP identity transformer, then you shouldn't be writing your application to pick up whatever implementation happens to be lying around on the classpath; you should instantiate the implementation you want explicitly.

    This can be difficult of course if the code that invokes the identity transform is something you didn't write yourself and can't easily change. In that case the best approach is to set the system property javax.xml.transform.TransformerFactory to select Xalan, and where you want to invoke Saxon, do it explicitly rather than relying on the JAXP factory search.