JDK-8250879 : Create XML File - no indentation - one long row
  • Type: Bug
  • Component: xml
  • Sub-Component: javax.xml.transform
  • Affected Version: 11,14,15
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • Submitted: 2020-07-29
  • Updated: 2020-08-01
  • Resolved: 2020-08-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdResolved
Related Reports
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows/Java 14

A DESCRIPTION OF THE PROBLEM :
Create new XML file from org.w3c.dom.Document. Use Transform class.

With Java 14 I have indented/formated only root element. Inside root element I have one long row of content.
The same code under Java 11 or Java 8 is indented/formated OK - nice structure.


REGRESSION : Last worked in version 11.0.8

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use method from "Source code for an executable test case".
Create org.w3c.dom.Document object with some deep structure

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<root>
    <child>
        <anotherChild>
...
        </anotherChild>
    </child>
</root>
ACTUAL -
<root>
    <child><anotherChild>...</anotherChild></child>
</root>

---------- BEGIN SOURCE ----------
package sk.xml.create.example;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

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;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Example {

    private static class PropertyContent {
        private final String value;
        private final String note;

        public PropertyContent(String value, String note) {
            this.value = value;
            this.note = note;
        }

        public String getValue() {
            return value;
        }

        public String getNote() {
            return note;
        }
    }

    private static Map<String, PropertyContent> propContentDefault = new HashMap<String, PropertyContent>() {{
        put("a", new PropertyContent("value_a", "note_a"));
        put("b", new PropertyContent("value_b", "note_b"));
        put("c", new PropertyContent("value_c", "note_c"));
        put("d", new PropertyContent("value_d", "note_d"));
    }};

    private static final String TEMP_EMPTY_ELEMENT_PLACEHOLDER = "__empty_prop_element__";

    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

        Document doc = docBuilder.newDocument();

        Element rootElement = doc.createElement("xliff");
        rootElement.setAttribute("xmlns", "urn:oasis:names:tc:xliff:document:1.2");
        rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        rootElement.setAttribute("version", "1.2");
        rootElement.setAttribute("xsi:schemaLocation", "urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-strict.xsd");

        doc.appendChild(rootElement);

        Element fileElement = doc.createElement("file");
        fileElement.setAttribute("xml:space", "preserve");
        fileElement.setAttribute("source-language", "en-US");
        fileElement.setAttribute("datatype", "javapropertyresourcebundle");
        fileElement.setAttribute("original", "MyConstants.properties");

        rootElement.appendChild(fileElement);

        Element headerElement = doc.createElement("header");
        headerElement.appendChild(doc.createTextNode(TEMP_EMPTY_ELEMENT_PLACEHOLDER));
        fileElement.appendChild(headerElement);

        Element bodyElement = doc.createElement("body");
        fileElement.appendChild(bodyElement);

        for (String propNameDefault : propContentDefault.keySet()) {
            Element transUnitElement = doc.createElement("trans-unit");
            transUnitElement.setAttribute("id", propNameDefault);
            bodyElement.appendChild(transUnitElement);

            Element sourceElement = doc.createElement("source");

            PropertyContent defaultPropContent = propContentDefault.get(propNameDefault);

            String defaultPropValue = defaultPropContent.getValue();
            String defaultPropNote = defaultPropContent.getNote();

            if (defaultPropValue.isEmpty()) {
                defaultPropValue = TEMP_EMPTY_ELEMENT_PLACEHOLDER;
            }
            sourceElement.appendChild(doc.createTextNode(defaultPropValue));
            transUnitElement.appendChild(sourceElement);

            if (defaultPropNote != null && !defaultPropNote.isEmpty()) {
                Element noteElement = doc.createElement("note");
                noteElement.setAttribute("xml:space", "preserve");
                noteElement.appendChild(doc.createTextNode(defaultPropNote));
                transUnitElement.appendChild(noteElement);
            }
        }

        TransformerFactory tranFactory = TransformerFactory.newInstance();
        Transformer transformer = tranFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");    // XML will be nicely formatted not in one line
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

        File tempFile = new File("c:/temp/xmlTestFile.xml");
        tempFile.getParentFile().mkdirs();

        StreamResult result = new StreamResult(tempFile);
        transformer.transform(new DOMSource(doc), result);
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Works with Java 8 and 11

FREQUENCY : always



Comments
Refer to JDK-8175793, the pretty print feature was updated in JDK 9 to observe the xml:space attribute. In your case, you are instructing the serializer to preserve all the white space by setting it to "preserve". If your intention is for the serializer to add additional white space (in order to achieve pretty print), you may remove the setting (e.g. fileElement.setAttribute("xml:space", "preserve")).
01-08-2020

The observations on Windows 10: JDK 8: Pass JDK 11: Fail JDK 14: Fail JDK 15: Fail
31-07-2020

This incident is probably a duplicate of JDK-8249867.
31-07-2020