United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 7150637 No newline emitted after XML decl in XSLT output
7150637 : No newline emitted after XML decl in XSLT output

Details
Type:
Bug
Submit Date:
2012-03-02
Status:
Closed
Updated Date:
2012-09-28
Project Name:
JDK
Resolved Date:
2012-04-06
Component:
xml
OS:
linux_ubuntu,linux
Sub-Component:
javax.xml.transform
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
7,7u4
Fixed Versions:
7u4

Related Reports
Duplicate:
Relates:

Sub Tasks

Description
Test program:

---%<---
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
public class JAXP7u4Regression {
    public static void main(String[] args) throws Exception {
        String data =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<r>\n" +
            "    <e/>\n" +
            "</r>\n";
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(data)));
        TransformerFactory tf = TransformerFactory.newInstance();
        String IDENTITY_XSLT_WITH_INDENT = // #5064280 workaround
            "<xsl:stylesheet version='1.0' " +
            "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' " +
            "xmlns:xalan='http://xml.apache.org/xslt' " +
            "exclude-result-prefixes='xalan'>" +
            "<xsl:output method='xml' indent='yes' xalan:indent-amount='4'/>" +
            "<xsl:template match='@*|node()'>" +
            "<xsl:copy>" +
            "<xsl:apply-templates select='@*|node()'/>" +
            "</xsl:copy>" +
            "</xsl:template>" +
            "</xsl:stylesheet>";
        Transformer t = tf.newTransformer(new StreamSource(new StringReader(IDENTITY_XSLT_WITH_INDENT)));
        t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        Source source = new DOMSource(doc);
        Result result = new StreamResult(System.out);
        t.transform(source, result);
    }
    private JAXP7u4Regression() {}
}
---%<---

Output in 7u3  (b04; Ubuntu, 32-bit JVM):

<?xml version="1.0" encoding="UTF-8"?>
<r>
    <e/>
</r>

vs. 7u4 (b14):

<?xml version="1.0" encoding="UTF-8"?><r>
    <e/>
</r>

Note the missing newline between the XML declaration and the root element.

                                    

Comments
EVALUATION

This is an issue introduced by an Apache update that although technically correct, was nonetheless an incompatible change. As reported in the CR, it caused NetBeans test failures and spurious reformatting of project metadata of users' projects that the version control tool would take as if there were real changes. The incompatible behavior would more than likely cause many problems to users' applications.

This patch adds an implementation specific property that can be used to essentially neutralize the Apache change to bring back the original behavior. It has been tested to have resolved the NetBeans issue with minimal effort in the NetBeans' part.

The use is:

static final String ORACLE_IS_STANDALONE = "http://www.oracle.com/xml/is-standalone";
//catch IllegalArgumentException when running with previous releases
try {
    transformer.setOutputProperty(ORACLE_IS_STANDALONE, "yes");
} catch (IllegalArgumentException e) {
    //expected for previous releases
}
                                     
2012-04-06
PUBLIC COMMENTS

Originally discovered as

  https://netbeans.org/bugzilla/show_bug.cgi?id=208909

Utility code encountering the problem:

  https://hg.netbeans.org/releases/raw-file/release71_fixes_base/openide.util/src/org/openide/xml/XMLUtil.java

and its unit tests

  https://hg.netbeans.org/releases/raw-file/release71_fixes_base/openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java
                                     
2012-03-02
EVALUATION

Presumably caused by some aspect of the JAXP upgrade (d9891683fc16 & 4a61ac055189).
                                     
2012-03-02
WORK AROUND

No simple workaround (not regressing other details checked by XMLUtilTest) yet known.


Using simply

        Transformer t = tf.newTransformer();

without the special identity transformer behaves poorly even on earlier versions of JAXP, hence the #5064280 workaround.


Using DOM 3 L&S

        DOMImplementationLS ls = (DOMImplementationLS) doc.getImplementation().getFeature("LS", "3.0");
        LSSerializer ser = ls.createLSSerializer();
        ser.getDomConfig().setParameter("format-pretty-print", true);
        LSOutput out = ls.createLSOutput();
        out.setByteStream(System.out);
        ser.write(doc, out);

works nicely in this case but fails in some more advanced cases, such as comments between the XML declaration and the root element.
                                     
2012-03-02
EVALUATION

Yes, it was an update to Apache Xalan 2.7.1.
                                     
2012-03-02



Hardware and Software, Engineered to Work Together