0

I wrote a program (I'm using JDK 11) to format an XML string; however, I want my program to contract empty elements. For example: <element></element> should become <element/>. I have written the below code which does not work:

        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
        transformer.setOutputProperty(OutputKeys.INDENT,"yes");
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"no");
        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,"yes");
        transformer.setOutputProperty(OutputKeys.METHOD,"xml");
        transformer.transform(new DOMSource(unformattedXml),new StreamResult(stringWriter));
        return stringWriter.toString();

How can I contract the empty elements?

  • I have ched this with jdk 11 and it is not reproduceable – Jens Sep 11 '18 at 08:14
  • What input string did you use? – RobotWizard Sep 11 '18 at 09:46
  • `Document document = db.parse(new ByteArrayInputStream("".getBytes("UTF-8")));` outout: ` ` – Jens Sep 11 '18 at 09:48
  • Your input works fine using my code. Can you try `"\n"` as input? – RobotWizard Sep 11 '18 at 09:49
  • `\n` is a valid charcter, so it is not an empty element! – Jens Sep 11 '18 at 09:50
  • I am well aware that \n is a character. My code was working fine and performing the contraction as expected when I used it on JDK 8. The problem appeared when I used JDK 11. – RobotWizard Sep 11 '18 at 09:54
  • I get same result in java8 and java11 ` ` – Jens Sep 11 '18 at 09:56
  • What is the actual Java class of the returned `Transformer`? I'm puzzled by the serialization property `http://www.oracle.com/xml/is-standalone` which is very non-standard: where is this documented? – Michael Kay Sep 11 '18 at 11:02
  • @MichaelKay I tried the code with and without the serialization property. Same result. I have used it due to this: https://stackoverflow.com/a/38773720/10270181 This is the class of the Transformer that gets loaded: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl – RobotWizard Sep 11 '18 at 11:19

1 Answers1

1

I don't know which XML libraries you are using. I just tried with raw installation and works fine for me.

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
//from w  w  w.  ja  va2 s.c om
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class Transform {

    public static void main(String[] args) throws Exception {
        String unformattedXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
                + "<note>\n"
                + "  <to>example</to>\n"
                + "  <from>Server</from>\n"
                + "  <heading>Reminder</heading>\n"
                + "  <body></body>\n"
                + "</note>";
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty("http://www.oracle.com/xml/is-standalone", "yes");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        StringWriter stringWriter = new StringWriter();
        transformer.transform(new DOMSource(convertStringToDocument(unformattedXml).getDocumentElement()), new StreamResult(stringWriter));
        String s = stringWriter.toString();
        System.out.println(s);
    }

    private static Document convertStringToDocument(String xmlStr) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(xmlStr)));
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

Output:

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>example</to>
  <from>Server</from>
  <heading>Reminder</heading>
  <body/>
</note>
Optional
  • 4,387
  • 4
  • 27
  • 45
  • These are my imports : import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; Maybe it is related to jdk 11? – RobotWizard Sep 11 '18 at 07:42
  • 1
    If it is not reproduceable, the question should closed – Jens Sep 11 '18 at 07:43
  • @RobotWizard Try to debug, which DocumentBuilder gets loaded. It will be loaded by DocumentBuilderFactory and what is the actual implementation of Transformer class you get. In debug you can see that, and then it will be easier to recommend. – Optional Sep 11 '18 at 07:44
  • @Optional this is the DocumentBuilder that gets loaded com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl and this is the the Transformer that gets loaded com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl – RobotWizard Sep 11 '18 at 08:08
  • I have same transformer and DocumentBuilder. – Optional Sep 11 '18 at 08:11
  • @Optional I ran your code on my input, it didn't work. The input I am using is `"\n"` – RobotWizard Sep 11 '18 at 08:23
  • @Jens, no if it's not reproducible then we need to dig more deeply to find out why it works for us and not for the OP. – Michael Kay Sep 11 '18 at 11:04
  • @MichaelKay ok. But not answer as "I can not reproduce it" – Jens Sep 11 '18 at 11:36
  • In theory this isn't an answer according to SO rules, but it's a helpful response and too complex to go in a comment, so my inclination is to ignore the rules. – Michael Kay Sep 11 '18 at 13:31