Search code examples
javaxmlcomments

Problem with inserting/appending comment before root node and after prolog with org.w3c.dom


Im trying to insert a comment with syntax version information before the first node of an xml document but for some reason it always gets appended after the last element. I cant use other libraries like XStream and such.

I have already tried to do this via the append and the insertBefore method but both of them yield the same result. Is it possible to do this just with the plain Document, Comment and Node or do I have to use a Transformer?

      Document doc = XmlDocumentUtil.createDocument();

      //Create root node
      Node rootNode = doc.createElement(NODE_DATA_CONFIGURATION);
      doc.appendChild(rootNode);

      //Create syntax identification comment
      Comment syntaxIdentification = doc.createComment(writeSyntaxIdentificationQE);
      doc.insertBefore(syntaxIdentification, rootNode);

      //Create revision information
      Element modificationNumber = doc.createElement("modificationNumber");
      modificationNumber.setTextContent(String.valueOf(configTable.getModificationNumber()));
      rootNode.appendChild(modificationNumber);

      Element modificationTime = doc.createElement("modificationTime");
      modificationTime.setTextContent(configTable.getModificationTime());
      rootNode.appendChild(modificationTime);

      Element modifier = doc.createElement("modifier");
      modifier.setTextContent(configTable.getModifier());
      rootNode.appendChild(modifier);

      for (...) {
         ... some data generation
      }

What I get:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<DataConfiguration>
    <modificationNumber>2</modificationNumber>
    <modificationTime>2019-07-25 07:42:28.804 +0200</modificationTime>
    <modifier>testuser</modifier>
    <someData idxFrom="4" idxTo="9"
        signalName="1" signalOffset="273.15" signalTemplate="asdf" skip="Y"/>
</DataConfiguration>
<!--SyntaxIdentification: 1.0-->

What I need:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--SyntaxIdentification: 1.0-->
<DataConfiguration>
    <modificationNumber>2</modificationNumber>
    <modificationTime>2019-07-25 07:42:28.804 +0200</modificationTime>
    <modifier>testuser</modifier>
    <someData idxFrom="4" idxTo="9"
        signalName="1" signalOffset="273.15" signalTemplate="asdf" skip="Y"/>
</DataConfiguration>

Solution

  • To me your code seems good overall. Seems like you are missing only text nodes.

    Here is full working code.

    package xml;
    
    import java.io.StringWriter;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    
    import org.w3c.dom.*;
    
    public class XMLComment {
    
        public static void main(String[] args) throws ParserConfigurationException, TransformerException {
    
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.newDocument();
    
            // Create root node
            Node rootNode = doc.createElement("DataConfiguration");
            doc.appendChild(rootNode);
    
            // Create syntax identification comment
            Comment syntaxIdentification = doc.createComment("SyntaxIdentification: 1.0");
            doc.insertBefore(syntaxIdentification, rootNode);
    
            // Create modificationNumber
            Node modificationNumber = doc.createElement("modificationNumber");
            Text mnText = doc.createTextNode("123456");
            modificationNumber.appendChild(mnText);
    
            // Create modificationTime
            Element modificationTime = doc.createElement("modificationTime");
            Text mtText = doc.createTextNode("2019-07-25 07:42:28.804 +0200");
            modificationTime.appendChild(mtText);
    
            rootNode.appendChild(modificationNumber);
            rootNode.appendChild(modificationTime);
            printXML(doc);
    
        }
    
        private static void printXML(Document doc) throws TransformerException {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            // initialize StreamResult with File object to save to file
            StreamResult result = new StreamResult(new StringWriter());
            DOMSource source = new DOMSource(doc);
            transformer.transform(source, result);
            String xmlString = result.getWriter().toString();
            System.out.println(xmlString);
        }
    }
    

    It will output, close to what exactly you are looking for.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!--SyntaxIdentification: 1.0--><DataConfiguration>
      <modificationNumber>123456</modificationNumber>
      <modificationTime>2019-07-25 07:42:28.804 +0200</modificationTime>
    </DataConfiguration>
    

    Hope it helps.