8223291: Whitespace is added to CDATA tags when using OutputKeys.INDENT to format XML

Reviewed-by: dfuchs, lancea
This commit is contained in:
Joe Wang 2019-07-03 16:30:19 +00:00
parent 307b7e3c04
commit 5c12a30062
8 changed files with 92 additions and 34 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -40,7 +40,7 @@ import com.sun.org.apache.xml.internal.serializer.utils.Utils;
* because it is used from another package. * because it is used from another package.
* *
* @xsl.usage internal * @xsl.usage internal
* @LastModified: Sept 2018 * @LastModified: July 2019
*/ */
public final class ToHTMLStream extends ToStream public final class ToHTMLStream extends ToStream
{ {
@ -719,7 +719,7 @@ public final class ToHTMLStream extends ToStream
public final void endDocument() throws org.xml.sax.SAXException public final void endDocument() throws org.xml.sax.SAXException
{ {
if (m_doIndent) { if (m_doIndent) {
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
flushPending(); flushPending();
if (m_doIndent && !m_isprevtext) if (m_doIndent && !m_isprevtext)
@ -782,7 +782,7 @@ public final class ToHTMLStream extends ToStream
if (m_doIndent) { if (m_doIndent) {
// will add extra one if having namespace but no matter // will add extra one if having namespace but no matter
m_childNodeNum++; m_childNodeNum++;
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
ElemContext elemContext = m_elemContext; ElemContext elemContext = m_elemContext;
@ -923,7 +923,7 @@ public final class ToHTMLStream extends ToStream
throws org.xml.sax.SAXException throws org.xml.sax.SAXException
{ {
if (m_doIndent) { if (m_doIndent) {
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
// deal with any pending issues // deal with any pending issues
if (m_cdataTagOpen) if (m_cdataTagOpen)
@ -1645,7 +1645,7 @@ public final class ToHTMLStream extends ToStream
{ {
if (m_doIndent) { if (m_doIndent) {
m_childNodeNum++; m_childNodeNum++;
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
// Process any pending starDocument and startElement first. // Process any pending starDocument and startElement first.
flushPending(); flushPending();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -51,7 +51,7 @@ import org.xml.sax.SAXException;
* serializers (xml, html, text ...) that write output to a stream. * serializers (xml, html, text ...) that write output to a stream.
* *
* @xsl.usage internal * @xsl.usage internal
* @LastModified: Sept 2018 * @LastModified: July 2019
*/ */
abstract public class ToStream extends SerializerBase { abstract public class ToStream extends SerializerBase {
@ -1231,7 +1231,7 @@ abstract public class ToStream extends SerializerBase {
m_elemContext.m_startTagOpen = false; m_elemContext.m_startTagOpen = false;
} }
if (!m_cdataTagOpen && shouldIndent()) if (!m_cdataTagOpen && shouldIndentForText())
indent(); indent();
boolean writeCDataBrackets = boolean writeCDataBrackets =
@ -1270,6 +1270,7 @@ abstract public class ToStream extends SerializerBase {
closeCDATA(); closeCDATA();
} }
m_isprevtext = true;
// time to fire off CDATA event // time to fire off CDATA event
if (m_tracer != null) if (m_tracer != null)
super.fireCDATAEvent(ch, old_start, length); super.fireCDATAEvent(ch, old_start, length);
@ -1536,11 +1537,13 @@ abstract public class ToStream extends SerializerBase {
} }
/** /**
* Used to flush the buffered characters when indentation is on, this method * Flushes the buffered characters when indentation is on. This method
* will be called when the next node is traversed. * is called before the next node is traversed.
* *
* @param isText indicates whether the node to be traversed is text
* @throws org.xml.sax.SAXException
*/ */
final protected void flushCharactersBuffer() throws SAXException { final protected void flushCharactersBuffer(boolean isText) throws SAXException {
try { try {
if (shouldFormatOutput() && m_charactersBuffer.isAnyCharactersBuffered()) { if (shouldFormatOutput() && m_charactersBuffer.isAnyCharactersBuffered()) {
if (m_elemContext.m_isCdataSection) { if (m_elemContext.m_isCdataSection) {
@ -1553,7 +1556,9 @@ abstract public class ToStream extends SerializerBase {
return; return;
} }
m_childNodeNum++; if (!isText) {
m_childNodeNum++;
}
boolean skipBeginningNewlines = false; boolean skipBeginningNewlines = false;
if (shouldIndentForText()) { if (shouldIndentForText()) {
indent(); indent();
@ -1846,7 +1851,7 @@ abstract public class ToStream extends SerializerBase {
if (m_doIndent) { if (m_doIndent) {
m_childNodeNum++; m_childNodeNum++;
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
if (m_needToCallStartDocument) if (m_needToCallStartDocument)
@ -2117,7 +2122,7 @@ abstract public class ToStream extends SerializerBase {
return; return;
if (m_doIndent) { if (m_doIndent) {
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
// namespaces declared at the current depth are no longer valid // namespaces declared at the current depth are no longer valid
// so get rid of them // so get rid of them
@ -2309,7 +2314,7 @@ abstract public class ToStream extends SerializerBase {
return; return;
if (m_doIndent) { if (m_doIndent) {
m_childNodeNum++; m_childNodeNum++;
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
if (m_elemContext.m_startTagOpen) if (m_elemContext.m_startTagOpen)
{ {
@ -2491,8 +2496,7 @@ abstract public class ToStream extends SerializerBase {
public void startCDATA() throws org.xml.sax.SAXException public void startCDATA() throws org.xml.sax.SAXException
{ {
if (m_doIndent) { if (m_doIndent) {
m_childNodeNum++; flushCharactersBuffer(true);
flushCharactersBuffer();
} }
m_cdataStartCalled = true; m_cdataStartCalled = true;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
*/ */
/* /*
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
@ -40,6 +40,7 @@ import org.xml.sax.SAXException;
* be viewed as internal or package private, this is not an API. * be viewed as internal or package private, this is not an API.
* *
* @xsl.usage internal * @xsl.usage internal
* @LastModified: July 2019
*/ */
public final class ToXMLStream extends ToStream public final class ToXMLStream extends ToStream
{ {
@ -200,7 +201,7 @@ public final class ToXMLStream extends ToStream
public void endDocument() throws org.xml.sax.SAXException public void endDocument() throws org.xml.sax.SAXException
{ {
if (m_doIndent) { if (m_doIndent) {
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
flushPending(); flushPending();
if (m_doIndent && !m_isprevtext) if (m_doIndent && !m_isprevtext)
@ -267,7 +268,7 @@ public final class ToXMLStream extends ToStream
if (m_doIndent) { if (m_doIndent) {
m_childNodeNum++; m_childNodeNum++;
flushCharactersBuffer(); flushCharactersBuffer(false);
} }
flushPending(); flushPending();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -60,7 +60,7 @@ import org.xml.sax.SAXException;
/* /*
* @test * @test
* @bug 6439439 8087303 8174025 * @bug 6439439 8087303 8174025 8223291
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true common.prettyprint.PrettyPrintTest * @run testng/othervm -DrunSecMngr=true common.prettyprint.PrettyPrintTest
* @run testng/othervm common.prettyprint.PrettyPrintTest * @run testng/othervm common.prettyprint.PrettyPrintTest
@ -382,7 +382,6 @@ public class PrettyPrintTest {
private Document toXmlDocument(String xmlString) throws Exception { private Document toXmlDocument(String xmlString) throws Exception {
InputSource xmlInputSource = new InputSource(new StringReader(xmlString)); InputSource xmlInputSource = new InputSource(new StringReader(xmlString));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(true);
DocumentBuilder xmlDocumentBuilder = dbf.newDocumentBuilder(); DocumentBuilder xmlDocumentBuilder = dbf.newDocumentBuilder();
Document node = xmlDocumentBuilder.parse(xmlInputSource); Document node = xmlDocumentBuilder.parse(xmlInputSource);
return node; return node;

View File

@ -1,3 +1 @@
<a> <a><![CDATA[ ]]></a>
<![CDATA[ ]]>
</a>

View File

@ -1,5 +1,3 @@
<a> <a><![CDATA[ abc def
<![CDATA[ abc def
line2 &a line2 &a
test]]> test]]></a>
</a>

View File

@ -1,6 +1,5 @@
<root> <root>
t t<![CDATA[ ]]>
<![CDATA[ ]]>
t t
<child1/> <child1/>

View File

@ -24,21 +24,79 @@
package transform; package transform;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter;
import java.util.Properties; import java.util.Properties;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamSource;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/* /*
* @test * @test
* @bug 8219705 * @bug 8219705 8223291
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng transform.OutputPropertiesTest * @run testng transform.OutputPropertiesTest
* @summary Verifies the output properties are set correctly * @summary Verifies the output properties are set correctly
*/ */
public class OutputPropertiesTest { public class OutputPropertiesTest {
/*
DataProvider: for testing indentation
Data: xml, expected result
*/
@DataProvider(name = "Indentation")
public Object[][] getData() {
String mix = "\n" +
" abc\n" +
" mix\n" +
" xyz\n" +
" ";
return new Object[][]{
{"abc<![CDATA[data]]>xyz", "abcdataxyz"},
{"abc<![CDATA[ & ]]>xyz", "abc & xyz"},
{"<![CDATA[data]]>", "data"},
{"abc<mix>mix</mix>xyz", mix}
};
}
/**
* bug 8223291
* Verifies that no extra indentation is added for CDATA.
* @param xml the xml content to be tested
* @param expected the expected result
* @throws Exception
*/
@Test(dataProvider = "Indentation")
public void testIndentation(String xml, String expected) throws Exception
{
StreamSource source = new StreamSource(new StringReader("<foo><bar>" + xml + "</bar></foo>"));
StreamResult result = new StreamResult(new StringWriter());
Transformer tform = TransformerFactory.newInstance().newTransformer();
tform.setOutputProperty(OutputKeys.INDENT, "yes");
tform.transform(source, result);
String xml1 = result.getWriter().toString();
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(xml1)));
String resultData = document.getElementsByTagName("bar")
.item(0)
.getTextContent();
Assert.assertEquals(resultData, expected);
}
@Test @Test
public void testOutputProperties() throws Exception { public void testOutputProperties() throws Exception {
String xslData = "<?xml version='1.0'?>" String xslData = "<?xml version='1.0'?>"
@ -70,4 +128,5 @@ public class OutputPropertiesTest {
prNames[i] + ": actual: " + value + ", expected: " + prValues[i]); prNames[i] + ": actual: " + value + ", expected: " + prValues[i]);
} }
} }
} }