diff --git a/docs/manual/OptionalTasks/junit.html b/docs/manual/OptionalTasks/junit.html index 92f1a791c..5d84a81cd 100644 --- a/docs/manual/OptionalTasks/junit.html +++ b/docs/manual/OptionalTasks/junit.html @@ -225,6 +225,10 @@ for all test cases. Custom formatters that need to implement org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter can be specified.

+

If you use the XML formatter, it may not include the same output +that your tests have written as some characters are illegal in XML +documents and will be dropped.

+ diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java index cfae10a8d..93a8b465b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLResultAggregator.java @@ -231,7 +231,7 @@ public class XMLResultAggregator extends Task implements XMLConstants { try { out = new FileOutputStream( file ); wri = new PrintWriter(new OutputStreamWriter(out, "UTF8")); - wri.write("\n"); + wri.write("\n"); (new DOMElementWriter()).write(doc.getDocumentElement(), wri, 0, " "); wri.flush(); // writers do not throw exceptions, so check for them. diff --git a/src/main/org/apache/tools/ant/util/DOMElementWriter.java b/src/main/org/apache/tools/ant/util/DOMElementWriter.java index c230e897a..a1765b71e 100644 --- a/src/main/org/apache/tools/ant/util/DOMElementWriter.java +++ b/src/main/org/apache/tools/ant/util/DOMElementWriter.java @@ -201,8 +201,8 @@ public class DOMElementWriter { } /** - * Escape <, > & ', " and control characters - * < 0x20 as their entities. + * Escape <, > & ', " as their entities and + * drop characters that are illegal in XML documents. */ public String encode(String value) { sb.setLength(0); @@ -230,17 +230,8 @@ public class DOMElementWriter { sb.append('&'); } break; - case '\t': - case '\n': - case '\r': - sb.append(c); - break; default: - if (c < 0x20) { - sb.append("&#x"); - sb.append(Integer.toHexString(c)); - sb.append(';'); - } else { + if (isLegalCharacter(c)) { sb.append(c); } break; @@ -250,7 +241,7 @@ public class DOMElementWriter { } /** - * Escape control characters < x20 as their entities. + * Drop characters that are illegal in XML documents. * *

See XML 1.0 2.2 http://www.w3.org/TR/1998/REC-xml-19980210#charsets.

@@ -259,22 +250,8 @@ public class DOMElementWriter { sb.setLength(0); for (int i = 0; i < value.length(); ++i) { char c = value.charAt(i); - switch (c) { - case '\t': - case '\n': - case '\r': + if (isLegalCharacter(c)) { sb.append(c); - break; - - default: - if (c < 0x20) { - sb.append("&#x"); - sb.append(Integer.toHexString(c)); - sb.append(';'); - } else { - sb.append(c); - } - break; } } return sb.toString(); @@ -314,4 +291,27 @@ public class DOMElementWriter { } return false; } + + /** + * Is the given character allowed inside an XML document? + * + *

See XML 1.0 2.2 http://www.w3.org/TR/1998/REC-xml-19980210#charsets.

+ * + * @since 1.10, Ant 1.5 + */ + public boolean isLegalCharacter(char c) { + if (c == 0x9 || c == 0xA || c == 0xD) { + return true; + } else if (c < 0x20) { + return false; + } else if (c <= 0xD7FF) { + return true; + } else if (c < 0xE000) { + return false; + } else if (c <= 0xFFFD) { + return true; + } + return false; + } } diff --git a/src/testcases/org/apache/tools/ant/util/DOMElementWriterTest.java b/src/testcases/org/apache/tools/ant/util/DOMElementWriterTest.java index 4091785d3..a14aef45a 100644 --- a/src/testcases/org/apache/tools/ant/util/DOMElementWriterTest.java +++ b/src/testcases/org/apache/tools/ant/util/DOMElementWriterTest.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2001 The Apache Software Foundation. All rights + * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -100,8 +100,23 @@ public class DOMElementWriterTest extends TestCase { assertEquals(""", w.encode("\"")); assertEquals("<", w.encode("<")); assertEquals("&", w.encode("&")); - assertEquals("", w.encode("\u0017")); + assertEquals("", w.encode("\u0017")); assertEquals("\"20;&", w.encodedata("\"20;&")); - assertEquals("", w.encodedata("\u0017")); + assertEquals("", w.encodedata("\u0017")); + } + + public void testIsLegalCharacter() { + assertTrue("0x00", !w.isLegalCharacter('\u0000')); + assertTrue("0x09", w.isLegalCharacter('\t')); + assertTrue("0x0A", w.isLegalCharacter('\n')); + assertTrue("0x0C", w.isLegalCharacter('\r')); + assertTrue("0x1F", !w.isLegalCharacter('\u001F')); + assertTrue("0x20", w.isLegalCharacter('\u0020')); + assertTrue("0xD7FF", w.isLegalCharacter('\uD7FF')); + assertTrue("0xD800", !w.isLegalCharacter('\uD800')); + assertTrue("0xDFFF", !w.isLegalCharacter('\uDFFF')); + assertTrue("0xE000", w.isLegalCharacter('\uE000')); + assertTrue("0xFFFD", w.isLegalCharacter('\uFFFD')); + assertTrue("0xFFFE", !w.isLegalCharacter('\uFFFE')); } }
Attribute