1
/* Copyright 2002-2005 Elliotte Rusty Harold
3
This library is free software; you can redistribute it and/or modify
4
it under the terms of version 2.1 of the GNU Lesser General Public
5
License as published by the Free Software Foundation.
7
This library is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU Lesser General Public License for more details.
12
You should have received a copy of the GNU Lesser General Public
13
License along with this library; if not, write to the
14
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15
Boston, MA 02111-1307 USA
17
You can contact Elliotte Rusty Harold by sending e-mail to
18
elharo@metalab.unc.edu. Please include the word "XOM" in the
19
subject line. The XOM home page is located at http://www.xom.nu/
24
import java.io.ByteArrayOutputStream;
25
import java.io.CharConversionException;
27
import java.io.FileNotFoundException;
28
import java.io.FileOutputStream;
29
import java.io.IOException;
30
import java.io.OutputStreamWriter;
31
import java.io.PrintStream;
32
import java.io.Reader;
33
import java.io.StringReader;
34
import java.io.ByteArrayInputStream;
35
import java.io.InputStream;
36
import java.io.UTFDataFormatException;
37
import java.io.Writer;
38
import java.lang.ref.WeakReference;
39
import java.lang.reflect.Constructor;
40
import java.lang.reflect.InvocationTargetException;
42
import org.xml.sax.Attributes;
43
import org.xml.sax.InputSource;
44
import org.xml.sax.Locator;
45
import org.xml.sax.SAXException;
46
import org.xml.sax.SAXNotRecognizedException;
47
import org.xml.sax.SAXNotSupportedException;
48
import org.xml.sax.SAXParseException;
49
import org.xml.sax.XMLFilter;
50
import org.xml.sax.XMLReader;
51
import org.xml.sax.helpers.AttributesImpl;
52
import org.xml.sax.helpers.LocatorImpl;
53
import org.xml.sax.helpers.XMLFilterImpl;
54
import org.xml.sax.helpers.XMLReaderFactory;
56
import nu.xom.Attribute;
57
import nu.xom.Builder;
58
import nu.xom.Comment;
59
import nu.xom.DocType;
60
import nu.xom.Document;
61
import nu.xom.Element;
62
import nu.xom.Elements;
63
import nu.xom.NodeFactory;
64
import nu.xom.ParsingException;
65
import nu.xom.ProcessingInstruction;
66
import nu.xom.Serializer;
67
import nu.xom.ValidityException;
68
import nu.xom.WellformednessException;
69
import nu.xom.XMLException;
74
* Tests building documents from streams, strings, files,
75
* and other input sources.
78
* @author Elliotte Rusty Harold
82
public class BuilderTest extends XOMTestCase {
85
private File inputDir = new File("data");
87
// This class tests error conditions, which Xerces
88
// annoyingly logs to System.err. So we hide System.err
89
// before each test and restore it after each test.
90
private PrintStream systemErr = System.err;
92
protected void setUp() {
93
System.setErr(new PrintStream(new ByteArrayOutputStream()));
97
protected void tearDown() {
98
System.setErr(systemErr);
102
// Custom parser to test what happens when parser supplies
104
private static class CustomReader extends XMLFilterImpl {
106
public void setFeature(String name, boolean value) {};
108
public void parse(InputSource in) throws SAXException {
109
this.getContentHandler().startDocument();
110
this.getContentHandler().startElement("87", "87", "87", new AttributesImpl());
111
this.getContentHandler().endElement("87", "87", "87");
112
this.getContentHandler().endDocument();
118
private static class DoNothingReader extends CustomReader {
120
public void parse(InputSource in) throws SAXException {}
125
private static class StartAndEndReader extends CustomReader {
127
public void parse(InputSource in) throws SAXException {
128
this.getContentHandler().startDocument();
129
this.getContentHandler().endDocument();
135
private static class StartOnlyReader extends CustomReader {
137
public void parse(InputSource in) throws SAXException {
138
this.getContentHandler().startDocument();
144
private static class EndOnlyReader extends CustomReader {
146
public void parse(InputSource in) throws SAXException {
147
this.getContentHandler().endDocument();
153
public BuilderTest(String name) {
158
// flag to turn on and off tests based on
159
// http://nagoya.apache.org/bugzilla/show_bug.cgi?id=24124
160
private boolean xercesBroken = false;
162
private String elementDeclaration = "<!ELEMENT root (#PCDATA)>";
163
private String defaultAttributeDeclaration
164
= "<!ATTLIST test name CDATA \"value\">";
165
private String attributeDeclaration
166
= "<!ATTLIST root anattribute CDATA #REQUIRED>";
167
private String attributeDeclaration2
168
= "<!ATTLIST root anotherattribute CDATA \"value\">";
169
private String unparsedEntityDeclaration
170
= "<!ENTITY hatch-pic SYSTEM " +
171
"\"http://www.example.com/images/cup.gif\" NDATA gif>";
172
private String unparsedEntityDeclarationPublic
173
= "<!ENTITY public-pic PUBLIC \"public ID\" " +
174
"\"http://www.example.com/images/cup.gif\" NDATA gif>";
175
private String internalEntityDeclaration
176
= "<!ENTITY Pub-Status \"" +
177
"This is a pre-release of the specification.\">";
178
private String externalEntityDeclarationPublic =
179
"<!ENTITY open-hatch "
180
+ "PUBLIC \"-//Textuality//TEXT Standard " +
181
"open-hatch boilerplate//EN\" "
182
+ "\"http://www.textuality.com/boilerplate/OpenHatch.xml\">";
183
private String externalEntityDeclarationSystem =
184
"<!ENTITY test SYSTEM " +
185
"\"http://www.textuality.com/boilerplate/OpenHatch.xml\">";
186
private String notationDeclarationSystem
187
= "<!NOTATION ISODATE SYSTEM "
188
+ "\"http://www.iso.ch/cate/d15903.html\">";
189
private String notationDeclarationPublicAndSystem
190
= "<!NOTATION DATE PUBLIC \"DATE PUBLIC ID\" "
191
+ "\"http://www.iso.ch/cate/d15903.html\">";
192
private String notationDeclarationPublic = "<!NOTATION gif PUBLIC "
193
+ "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\">";
195
private String source = "<!DOCTYPE test [\r\n"
196
+ elementDeclaration + "\n"
197
+ attributeDeclaration + "\n"
198
+ defaultAttributeDeclaration + "\n"
199
+ attributeDeclaration2 + "\n"
200
+ internalEntityDeclaration + "\n"
201
+ externalEntityDeclarationPublic + "\n"
202
+ externalEntityDeclarationSystem + "\n"
203
+ unparsedEntityDeclaration + "\n"
204
+ unparsedEntityDeclarationPublic + "\n"
205
+ notationDeclarationPublic + "\n"
206
+ notationDeclarationSystem + "\n"
207
+ notationDeclarationPublicAndSystem + "\n"
209
+ "<?xml-stylesheet href=\"file.css\" type=\"text/css\"?>"
211
+ "<test xmlns:xlink='http://www.w3.org/TR/1999/xlink'>Hello dear"
212
+ "\r\n<em id=\"p1\" xmlns:none=\"http://www.example.com\">"
213
+ "very important</em>"
214
+ "<span xlink:type='simple'>here's the link</span>\r\n"
215
+ "<svg:svg xmlns:svg='http://www.w3.org/TR/2000/svg'>"
216
+ "<svg:text>text in a namespace</svg:text></svg:svg>\r\n"
217
+ "<svg xmlns='http://www.w3.org/TR/2000/svg'><text>text in a "
218
+ "namespace</text></svg></test>\r\n<!--epilog-->";
220
private String validDoc = "<!DOCTYPE test [\r\n"
221
+ "<!ELEMENT test (#PCDATA)>\n"
223
+ "<?xml-stylesheet href=\"file.css\" type=\"text/css\"?>"
225
+ "<test>Hello dear</test>"
228
private Builder builder = new Builder();
229
private Builder validator = new Builder(true);
230
private String base = "http://www.example.com/";
232
private String attributeDoc = "<!DOCTYPE test [\n"
233
+ "<!ELEMENT test (#PCDATA)>\n"
234
+ "<!NOTATION GIF SYSTEM \"text/gif\">\n"
235
+ "<!ENTITY data SYSTEM \"http://www.example.org/cup.gif\">\n"
236
+ "<!ATTLIST test notationatt NOTATION (GIF) \"GIF\">\n"
237
+ "<!ATTLIST test cdataatt CDATA \"GIF\">\n"
238
+ "<!ATTLIST test entityatt ENTITY \"data\">\n"
239
+ "<!ATTLIST test entitiesatt ENTITIES \"data\">\n"
240
+ "<!ATTLIST test nmtokenatt NMTOKEN \" 1 \">\n"
241
+ "<!ATTLIST test nmtokensatt NMTOKENS \" 1 2 3 \">\n"
242
+ "<!ATTLIST test idatt ID \" p1 \">\n"
243
+ "<!ATTLIST test idrefatt IDREF \" p1 \">\n"
244
+ "<!ATTLIST test idrefsatt IDREFS \" p1 p2 \">\n"
246
+ "<test>Hello dear</test>";
249
public void testDoNothingParser()
250
throws ParsingException, IOException {
253
XMLReader parser = new DoNothingReader();
254
Builder builder = new Builder(parser);
255
builder.build("http://www.example.org/");
256
fail("built from bad data");
258
catch (ParsingException success) {
259
assertNotNull(success.getMessage());
260
assertEquals("http://www.example.org/", success.getURI());
266
public void testStartAndEndParser()
267
throws ParsingException, IOException {
269
XMLReader parser = new StartAndEndReader();
270
Builder builder = new Builder(parser);
271
Document doc = builder.build("http://www.example.org/");
272
assertNotNull(doc.getRootElement());
277
public void testStartOnlyParser()
278
throws ParsingException, IOException {
280
XMLReader parser = new StartOnlyReader();
281
Builder builder = new Builder(parser);
282
Document doc = builder.build("http://www.example.org/");
283
assertNotNull(doc.getRootElement());
288
public void testEndOnlyParser()
289
throws ParsingException, IOException {
292
XMLReader parser = new EndOnlyReader();
293
Builder builder = new Builder(parser);
294
builder.build("http://www.example.org/");
295
fail("built from bad data");
297
catch (ParsingException success) {
298
assertTrue(success.getCause() instanceof NullPointerException);
304
public void testBuildInternalDTDSubsetWithFixedDefaultAttributeValue()
305
throws ParsingException, IOException {
307
String doctype = "<!DOCTYPE xsl:stylesheet [\n"
308
+ "<!ATTLIST a b CDATA #FIXED \"c\">]>";
309
String document = doctype + "\n<root/>";
310
Builder builder = new Builder();
311
Document doc = builder.build(document, null);
312
DocType dt = doc.getDocType();
313
String internalDTDSubset = dt.getInternalDTDSubset();
314
assertTrue(internalDTDSubset.indexOf("#FIXED \"c\"") > 0);
319
public void testNotationAttributeType()
320
throws IOException, ParsingException {
322
Reader reader = new StringReader(attributeDoc);
323
Document document = builder.build(reader);
324
Element root = document.getRootElement();
325
Attribute att = root.getAttribute("notationatt");
326
assertEquals(Attribute.Type.NOTATION, att.getType());
331
public void testCDATAAttributeType()
332
throws IOException, ParsingException {
334
Reader reader = new StringReader(attributeDoc);
335
Document document = builder.build(reader);
336
Element root = document.getRootElement();
337
Attribute att = root.getAttribute("cdataatt");
338
assertEquals(Attribute.Type.CDATA, att.getType());
343
public void testEntityAttributeType()
344
throws IOException, ParsingException {
346
Reader reader = new StringReader(attributeDoc);
347
Document document = builder.build(reader);
348
Element root = document.getRootElement();
349
Attribute att = root.getAttribute("entityatt");
350
assertEquals(Attribute.Type.ENTITY, att.getType());
355
public void testEntitiesAttributeType()
356
throws IOException, ParsingException {
358
Reader reader = new StringReader(attributeDoc);
359
Document document = builder.build(reader);
360
Element root = document.getRootElement();
361
Attribute att = root.getAttribute("entitiesatt");
362
assertEquals(Attribute.Type.ENTITIES, att.getType());
367
public void testNameTokenAttributeType()
368
throws IOException, ParsingException {
370
Reader reader = new StringReader(attributeDoc);
371
Document document = builder.build(reader);
372
Element root = document.getRootElement();
373
Attribute att = root.getAttribute("nmtokenatt");
374
assertEquals(Attribute.Type.NMTOKEN, att.getType());
375
assertEquals("1", att.getValue());
380
// I'm specifically worried about a Xerces runtime MalformedURIException here
381
public void testIllegalSystemIDThrowsRightException() {
383
String document = "<!DOCTYPE root SYSTEM \"This is not a URI\"><root/>";
385
builder.build(document, null);
387
catch (Exception ex) {
388
assertTrue(ex instanceof ParsingException);
394
public void testNameTokensAttributeType()
395
throws IOException, ParsingException {
397
Reader reader = new StringReader(attributeDoc);
398
Document document = builder.build(reader);
399
Element root = document.getRootElement();
400
Attribute att = root.getAttribute("nmtokensatt");
401
assertEquals(Attribute.Type.NMTOKENS, att.getType());
402
assertEquals("1 2 3", att.getValue());
407
// verify that XML 1.1 is not supported
408
public void testXML11() throws IOException {
410
String data = "<?xml version='1.1'?><root/>";
412
builder.build(data, "http://www.example.com");
413
fail("XML 1.1 allowed");
415
catch (ParsingException ex) {
416
assertNotNull(ex.getMessage());
422
// verify that XML 1.2 is not supported
423
public void testXML12() throws IOException {
425
String data = "<?xml version='1.2'?><root/>";
427
builder.build(data, "http://www.example.com");
428
fail("XML 1.2 allowed");
430
catch (ParsingException ex) {
431
assertNotNull(ex.getMessage());
437
// verify that XML 2.0 is not supported
438
public void testXML20() throws IOException {
440
String data = "<?xml version='2.0'?><root/>";
442
builder.build(data, "http://www.example.com");
443
fail("XML 2.0 allowed");
445
catch (ParsingException ex) {
446
assertNotNull(ex.getMessage());
452
public void testIDAttributeType()
453
throws IOException, ParsingException {
455
Reader reader = new StringReader(attributeDoc);
456
Document document = builder.build(reader);
457
Element root = document.getRootElement();
458
Attribute att = root.getAttribute("idatt");
459
assertEquals(Attribute.Type.ID, att.getType());
460
assertEquals("p1", att.getValue());
465
public void testIDREFAttributeType()
466
throws IOException, ParsingException {
468
Reader reader = new StringReader(attributeDoc);
469
Document document = builder.build(reader);
470
Element root = document.getRootElement();
471
Attribute att = root.getAttribute("idrefatt");
472
assertEquals(Attribute.Type.IDREF, att.getType());
473
assertEquals("p1", att.getValue());
478
public void testIDREFSAttributeType()
479
throws IOException, ParsingException {
481
Reader reader = new StringReader(attributeDoc);
482
Document document = builder.build(reader);
483
Element root = document.getRootElement();
484
Attribute att = root.getAttribute("idrefsatt");
485
assertEquals(Attribute.Type.IDREFS, att.getType());
486
assertEquals("p1 p2", att.getValue());
491
public void testBuildFromReader()
492
throws IOException, ParsingException {
494
Reader reader = new StringReader(source);
495
Document document = builder.build(reader);
497
assertEquals("", document.getBaseURI());
502
public void testBuildFromReaderWithBase()
503
throws IOException, ParsingException {
505
Reader reader = new StringReader(source);
506
Document document = builder.build(reader, base);
508
assertEquals(base, document.getBaseURI());
513
private static class NoLocator extends XMLFilterImpl {
515
public NoLocator(XMLReader reader) {
519
public void setDocumentLocator(Locator locator) {}
524
public void testBuildWithoutLocator()
525
throws IOException, ParsingException, SAXException {
527
XMLReader xerces = XMLReaderFactory.createXMLReader(
528
"org.apache.xerces.parsers.SAXParser");
529
XMLReader filter = new NoLocator(xerces);
531
Builder builder = new Builder(filter);
532
Document document = builder.build(source, "http://www.example.org/");
534
assertEquals("http://www.example.org/", document.getBaseURI());
539
private static class WeirdAttributeTypes extends XMLFilterImpl {
541
public WeirdAttributeTypes(XMLReader reader) {
545
public void startElement(String uri, String localName,
546
String qualifiedName, Attributes atts) throws SAXException {
548
AttributesImpl newAtts = new AttributesImpl(atts);
549
for (int i = 0; i < newAtts.getLength(); i++) {
550
newAtts.setType(i, "WEIRD");
553
super.startElement(uri, localName, qualifiedName, newAtts);
560
public void testWeirdAttributeTypes()
561
throws IOException, ParsingException, SAXException {
563
XMLReader xerces = XMLReaderFactory.createXMLReader(
564
"org.apache.xerces.parsers.SAXParser");
565
XMLReader filter = new WeirdAttributeTypes(xerces);
567
Builder builder = new Builder(filter);
568
Document document = builder.build(attributeDoc, "http://www.example.org/");
569
Element root = document.getRootElement();
570
assertTrue(root.getAttributeCount() > 0);
571
for (int i = 0; i < root.getAttributeCount(); i++) {
572
assertEquals(Attribute.Type.UNDECLARED, root.getAttribute(i).getType());
578
// Here we're faking the non-standard behavior of some older parsers
579
private static class ParenthesizedEnumeratedAttributeTypes extends XMLFilterImpl {
581
public ParenthesizedEnumeratedAttributeTypes(XMLReader reader) {
585
public void startElement(String uri, String localName,
586
String qualifiedName, Attributes atts) throws SAXException {
588
AttributesImpl newAtts = new AttributesImpl(atts);
589
for (int i = 0; i < newAtts.getLength(); i++) {
590
newAtts.setType(i, "(test, data, value)");
593
super.startElement(uri, localName, qualifiedName, newAtts);
600
public void testParenthesizedEnumeratedAttributeTypes()
601
throws IOException, ParsingException, SAXException {
603
XMLReader xerces = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
604
XMLReader filter = new ParenthesizedEnumeratedAttributeTypes(xerces);
606
Builder builder = new Builder(filter);
607
Document document = builder.build(attributeDoc, "http://www.example.org/");
608
Element root = document.getRootElement();
609
assertTrue(root.getAttributeCount() > 0);
610
for (int i = 0; i < root.getAttributeCount(); i++) {
611
assertEquals(Attribute.Type.ENUMERATION, root.getAttribute(i).getType());
617
public void testBuildFromInputStreamWithBase()
618
throws IOException, ParsingException {
619
InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
620
Document document = builder.build(in, base);
622
assertEquals(base, document.getBaseURI());
626
public void testBuildFromInputStreamWithoutBase()
627
throws IOException, ParsingException {
628
InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
629
Document document = builder.build(in);
631
assertEquals("", document.getBaseURI());
635
public void testBuildFromStringWithBase()
636
throws IOException, ParsingException {
637
Document document = builder.build(source, base);
639
assertEquals(base, document.getBaseURI());
643
public void testBuildDocumentThatUsesDoubleQuoteNumericCharacterReferenceInEntityDeclaration()
644
throws IOException, ParsingException {
646
String data = "<!DOCTYPE doc [\n"
647
+ "<!ELEMENT doc (#PCDATA)>"
648
+ " <!ENTITY e \""\">\n"
651
Document document = builder.build(data, null);
653
Document roundtrip = builder.build(document.toXML(), null);
654
assertEquals(document, roundtrip);
659
public void testBuildDocumentThatDeclaresStandardEntityReferences()
660
throws IOException, ParsingException {
662
String data = "<!DOCTYPE doc [\n"
663
+ "<!ELEMENT doc (#PCDATA)>"
664
+ "<!ENTITY lt \"&#60;\">\n"
665
+ "<!ENTITY gt \">\">\n"
666
+ "<!ENTITY amp \"&#38;\">\n"
667
+ "<!ENTITY apos \"'\">\n"
668
+ "<!ENTITY quot \""\">\n"
671
Document document = builder.build(data, null);
672
Document roundtrip = builder.build(document.toXML(), null);
673
assertEquals(document, roundtrip);
678
public void testBuildDocumentThatUsesAmpersandNumericCharacterReferenceInEntityDeclaration()
679
throws IOException, ParsingException {
681
String data = "<!DOCTYPE doc [\n"
682
+ "<!ELEMENT doc (#PCDATA)>"
683
+ " <!ENTITY e \"&\">\n"
686
Document document = builder.build(data, null);
688
Document roundtrip = builder.build(document.toXML(), null);
689
assertEquals(document, roundtrip);
694
public void testBuildDocumentThatUsesDoubleQuoteNumericCharacterReferenceInAttributeDeclaration()
695
throws IOException, ParsingException {
697
String data = "<!DOCTYPE doc [\n"
698
+ "<!ATTLIST root test (CDATA) \"4\">\n"
701
Document document = builder.build(data, null);
703
Document roundtrip = builder.build(document.toXML(), null);
704
assertEquals(document, roundtrip);
709
public void testMemoryFreedByBuilder()
710
throws IOException, ParsingException, InterruptedException {
712
String data = "<root />";
714
Document document = builder.build(data, null);
715
WeakReference ref = new WeakReference(document);
721
assertNull(ref.get());
726
public void testBuildFromInvalidDoc()
727
throws IOException, ParsingException {
730
validator.build(source, base);
731
fail("Built invalid doc");
733
catch (ValidityException ex) {
734
Document document = ex.getDocument();
735
// Can't do a full verify just yet due to bugs in Xerces
736
// verify(ex.getDocument());
737
assertTrue(document.getChild(1) instanceof ProcessingInstruction);
738
assertTrue(document.getChild(2) instanceof Comment);
739
DocType doctype = document.getDocType();
740
Element root = document.getRootElement();
742
// assertEquals(1, root.getAttributeCount());
743
// assertEquals("value", root.getAttributeValue("name"));
744
assertEquals("test", root.getQualifiedName());
745
assertEquals("test", root.getLocalName());
746
assertEquals("", root.getNamespaceURI());
748
assertTrue(doctype != null);
749
assertTrue(document.getChild(0) instanceof DocType);
750
assertTrue(document.getChild(4) instanceof Comment);
751
assertTrue(document.getChild(2) instanceof Comment);
752
assertEquals(" test ", document.getChild(2).getValue());
753
assertEquals("epilog", document.getChild(4).getValue());
754
assertTrue(document.getChild(1) instanceof ProcessingInstruction);
755
assertEquals("test", doctype.getRootElementName());
756
assertNull(doctype.getPublicID());
757
assertNull(doctype.getSystemID());
759
String internalDTDSubset = doctype.getInternalDTDSubset();
762
internalDTDSubset.indexOf(elementDeclaration) > 0
766
internalDTDSubset.indexOf(attributeDeclaration) > 0
770
internalDTDSubset.indexOf(attributeDeclaration2) > 0
774
internalDTDSubset.indexOf(internalEntityDeclaration) > 0
778
internalDTDSubset.indexOf(externalEntityDeclarationPublic) > 0
782
internalDTDSubset.indexOf(externalEntityDeclarationSystem) > 0
786
internalDTDSubset.indexOf(unparsedEntityDeclaration) > 0
790
internalDTDSubset.indexOf(unparsedEntityDeclarationPublic) > 0
794
internalDTDSubset.indexOf(notationDeclarationPublic) > 0
798
internalDTDSubset.indexOf(notationDeclarationSystem) > 0
802
internalDTDSubset.indexOf(notationDeclarationPublicAndSystem) > 0
810
public void testBuildFromStringWithNullBase()
811
throws IOException, ParsingException {
812
Document document = builder.build(source, null);
814
assertEquals("", document.getBaseURI());
818
private void verify(Document document) {
820
assertTrue(document.getChild(1) instanceof ProcessingInstruction);
821
assertTrue(document.getChild(2) instanceof Comment);
822
DocType doctype = document.getDocType();
823
Element root = document.getRootElement();
825
assertEquals(1, root.getAttributeCount());
826
assertEquals("value", root.getAttributeValue("name"));
827
assertEquals("test", root.getQualifiedName());
828
assertEquals("test", root.getLocalName());
829
assertEquals("", root.getNamespaceURI());
831
assertTrue(doctype != null);
832
assertTrue(document.getChild(0) instanceof DocType);
833
assertTrue(document.getChild(4) instanceof Comment);
834
assertTrue(document.getChild(2) instanceof Comment);
835
assertEquals(" test ", document.getChild(2).getValue());
836
assertEquals("epilog", document.getChild(4).getValue());
837
assertTrue(document.getChild(1) instanceof ProcessingInstruction);
838
assertEquals("test", doctype.getRootElementName());
839
assertNull(doctype.getPublicID());
840
assertNull(doctype.getSystemID());
842
String internalDTDSubset = doctype.getInternalDTDSubset();
845
internalDTDSubset.indexOf(elementDeclaration) > 0
849
internalDTDSubset.indexOf(attributeDeclaration) > 0
853
internalDTDSubset.indexOf(attributeDeclaration2) > 0
857
internalDTDSubset.indexOf(internalEntityDeclaration) > 0
861
internalDTDSubset.indexOf(externalEntityDeclarationPublic) > 0
865
internalDTDSubset.indexOf(externalEntityDeclarationSystem) > 0
869
internalDTDSubset.indexOf(unparsedEntityDeclaration) > 0
873
internalDTDSubset.indexOf(unparsedEntityDeclarationPublic) > 0
877
internalDTDSubset.indexOf(notationDeclarationPublic) > 0
881
internalDTDSubset.indexOf(notationDeclarationSystem) > 0
885
internalDTDSubset.indexOf(notationDeclarationPublicAndSystem) > 0
891
public void testValidateFromReader()
892
throws IOException, ParsingException {
894
Reader reader1 = new StringReader(validDoc);
895
Document document1 = validator.build(reader1);
896
assertEquals("", document1.getBaseURI());
897
Reader reader2 = new StringReader(validDoc);
898
Document document2 = builder.build(reader2);
899
assertEquals(document2, document1);
904
public void testDocumentWithDefaultNamespaceOnPrefixedElement()
905
throws IOException, ParsingException {
907
Reader reader = new StringReader("<pre:root " +
908
"xmlns='http://www.example.org/' " +
909
"xmlns:pre='http://www.cafeconleche.org/'/>");
910
Document document = builder.build(reader);
911
Element root = document.getRootElement();
912
assertEquals("http://www.example.org/", root.getNamespaceURI(""));
913
assertEquals("http://www.cafeconleche.org/", root.getNamespaceURI("pre"));
914
assertEquals("http://www.cafeconleche.org/", root.getNamespaceURI());
919
public void testValidateFromReaderWithBase()
920
throws IOException, ParsingException {
922
Reader reader = new StringReader(validDoc);
923
Document document = validator.build(reader, base);
924
assertEquals(base, document.getBaseURI());
925
Reader reader2 = new StringReader(validDoc);
926
Document document2 = builder.build(reader2);
927
assertEquals(document2, document);
932
public void testValidateFromInputStreamWithBase()
933
throws IOException, ParsingException {
935
InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
936
Document document = validator.build(in, base);
937
assertEquals(base, document.getBaseURI());
938
Reader reader2 = new StringReader(validDoc);
939
Document document2 = builder.build(reader2);
940
assertEquals(document2, document);
945
public void testValidateInSeries()
946
throws IOException, ParsingException {
949
Reader reader = new StringReader(source);
950
validator.build(reader);
951
fail("Allowed invalid doc");
953
catch (ValidityException success) {
954
assertNotNull(success.getMessage());
956
// now make sure validating a valid document doesn't
957
// throw an exception
958
InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
959
validator.build(in, base);
964
public void testValidateFromInputStreamWithoutBase()
965
throws IOException, ParsingException {
967
InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
968
Document document = validator.build(in);
969
assertEquals("", document.getBaseURI());
970
Reader reader2 = new StringReader(validDoc);
971
Document document2 = builder.build(reader2);
972
assertEquals(document2, document);
977
public void testValidateFromStringWithBase()
978
throws IOException, ParsingException {
980
Document document = validator.build(validDoc, base);
981
assertEquals(base, document.getBaseURI());
982
Reader reader2 = new StringReader(validDoc);
983
Document document2 = builder.build(reader2);
984
assertEquals(document2, document);
989
public void testValidateWithCrimson()
990
throws IOException, ParsingException {
994
crimson = XMLReaderFactory.createXMLReader(
995
"org.apache.crimson.parser.XMLReaderImpl");
997
catch (SAXException ex) {
998
// can't test Crimson if you can't load it
1001
Builder validator = new Builder(crimson, true);
1002
Document document = validator.build(validDoc, base);
1003
assertEquals(base, document.getBaseURI());
1004
Reader reader2 = new StringReader(validDoc);
1005
Document document2 = builder.build(reader2);
1006
assertEquals(document2, document);
1011
public void testNotationAttributeTypeWithCrimson()
1012
throws IOException, ParsingException {
1016
crimson = XMLReaderFactory.createXMLReader(
1017
"org.apache.crimson.parser.XMLReaderImpl");
1019
catch (SAXException ex) {
1020
// can't test Crimson if you can't load it
1024
String data = " <!DOCTYPE doc [\n"
1025
+ "<!ATTLIST e a NOTATION (n) #IMPLIED>\n"
1026
+ "<!ELEMENT document (e)*>\n"
1027
+ "<!ELEMENT e (#PCDATA)>\n"
1028
+ "<!NOTATION n PUBLIC \"whatever\">"
1031
Builder builder = new Builder(crimson);
1032
Document document = builder.build(data, base);
1034
String s = document.toXML();
1035
Document roundTrip = builder.build(s, base);
1036
assertEquals(document, roundTrip);
1041
public void testEnumerationAttributeType()
1042
throws IOException, ParsingException {
1046
crimson = XMLReaderFactory.createXMLReader(
1047
"org.apache.crimson.parser.XMLReaderImpl");
1049
catch (SAXException ex) {
1050
// can't test Crimson if you can't load it
1053
Builder builder = new Builder(crimson, false);
1054
String doc = "<!DOCTYPE root [" +
1055
"<!ATTLIST root att (yes | no) #IMPLIED>" +
1056
"]><root att='yes'/>";
1057
Document document = builder.build(doc, base);
1058
Element root = document.getRootElement();
1059
Attribute att = root.getAttribute(0);
1060
assertEquals(Attribute.Type.ENUMERATION, att.getType());
1065
public void testWarningDoesNotStopBuild()
1066
throws IOException, ParsingException, SAXException {
1070
xerces = XMLReaderFactory.createXMLReader(
1071
"org.apache.xerces.parsers.SAXParser");
1073
catch (SAXException ex) {
1074
// can't test Xerces if you can't load it
1077
// This document generates a warning due to the duplicate
1078
// attribute declaration
1080
"http://apache.org/xml/features/validation/warn-on-duplicate-attdef",
1082
Builder builder = new Builder(xerces, true);
1083
Document document = builder.build("<!DOCTYPE root [" +
1084
"<!ELEMENT root ANY>" +
1085
"<!ATTLIST root b CDATA #IMPLIED>" +
1086
"<!ATTLIST root b NMTOKEN #REQUIRED>" +
1087
"]><root b='test'/>", base);
1088
// The main test is that the document is built successfully.
1089
assertEquals(2, document.getChildCount());
1090
assertEquals("root", document.getRootElement().getQualifiedName());
1095
private static class EntitySkipper extends XMLFilterImpl {
1097
public EntitySkipper(XMLReader reader) {
1101
public void characters(char[] data, int start, int length)
1102
throws SAXException {
1103
super.skippedEntity("name");
1109
public void testSkippedEntityThrowsParsingException()
1110
throws IOException, ParsingException, SAXException {
1112
XMLReader xerces = XMLReaderFactory.createXMLReader(
1113
"org.apache.xerces.parsers.SAXParser");
1114
XMLReader filter = new EntitySkipper(xerces);
1116
Builder builder = new Builder(filter, true);
1118
builder.build("<root>replace</root>", base);
1119
fail("Allowed skipped entity");
1121
catch (ParsingException success) {
1122
assertNotNull(success.getMessage());
1128
public void testValidateFromStringWithNullBase()
1129
throws IOException, ParsingException {
1130
Document document = validator.build(validDoc, null);
1131
assertEquals("", document.getBaseURI());
1132
Reader reader2 = new StringReader(validDoc);
1133
Document document2 = builder.build(reader2);
1134
assertEquals(document2, document);
1138
public void testCannotBuildNamespaceMalformedDocument()
1139
throws IOException {
1142
builder.build("<root:root/>", null);
1143
fail("Builder allowed undeclared prefix");
1145
catch (ParsingException success) {
1146
assertNotNull(success.getMessage());
1152
public void testInvalidDocFromReader()
1153
throws IOException, ParsingException {
1155
Reader reader = new StringReader(source);
1157
validator.build(reader);
1158
fail("Allowed invalid doc");
1160
catch (ValidityException success) {
1161
assertNotNull(success.getMessage());
1162
assertTrue(success.getErrorCount() > 0);
1163
for (int i = 0; i < success.getErrorCount(); i++) {
1164
assertNotNull(success.getValidityError(i));
1165
assertTrue(success.getLineNumber(i) >= -1);
1166
assertTrue(success.getColumnNumber(i) >= -1);
1168
if (!xercesBroken) {
1169
Document doc = builder.build(new StringReader(source));
1170
this.verify(success.getDocument());
1171
assertEquals(doc, success.getDocument());
1178
public void testNamespaceMalformedDocumentWithCrimson()
1179
throws IOException {
1181
StringReader reader = new StringReader("<root:root/>");
1184
crimson = XMLReaderFactory.createXMLReader(
1185
"org.apache.crimson.parser.XMLReaderImpl");
1187
catch (SAXException ex) {
1188
// No Crimson in classpath; therefore can't test it
1191
Builder builder = new Builder(crimson);
1193
builder.build(reader);
1194
fail("Crimson allowed namespace malformed doc");
1196
catch (ParsingException success) {
1197
assertNotNull(success.getMessage());
1203
public void testValidateNamespaceMalformedInvalidDocumentWithCrimson()
1204
throws IOException {
1206
StringReader reader = new StringReader("<!DOCTYPE root [" +
1207
"<!ELEMENT root (a)>\n" +
1208
"<!ELEMENT a (#PCDATA)> \n" +
1210
"<root><b:b /></root>");
1213
crimson = XMLReaderFactory.createXMLReader(
1214
"org.apache.crimson.parser.XMLReaderImpl");
1216
catch (SAXException ex) {
1217
// No Crimson in classpath; therefore can't test it
1220
Builder builder = new Builder(crimson);
1222
builder.build(reader);
1223
fail("Crimson allowed namespace malformed doc");
1225
catch (ValidityException ex) {
1226
fail("Crimson should have thrown ParsingException instead");
1228
catch (ParsingException success) {
1229
assertNotNull(success.getMessage());
1235
public void testInvalidDocFromReaderWithBase()
1236
throws IOException, ParsingException {
1238
Reader reader1 = new StringReader(source);
1240
validator.build(reader1, base);
1241
fail("Allowed invalid doc");
1243
catch (ValidityException ex) {
1244
assertNotNull(ex.getMessage());
1245
assertEquals(base, ex.getURI());
1246
assertTrue(ex.getErrorCount() > 0);
1247
for (int i = 0; i < ex.getErrorCount(); i++) {
1248
assertNotNull(ex.getValidityError(i));
1249
assertTrue(ex.getLineNumber(i) >= -1);
1250
assertTrue(ex.getColumnNumber(i) >= -1);
1252
if (!xercesBroken) {
1253
Document doc = builder.build(new StringReader(source), base);
1254
this.verify(ex.getDocument());
1255
assertEquals(doc, ex.getDocument());
1262
public void testInvalidDocFromInputStreamWithBase()
1263
throws IOException, ParsingException {
1265
InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
1267
validator.build(in, base);
1268
fail("Allowed invalid doc");
1270
catch (ValidityException ex) {
1271
assertNotNull(ex.getMessage());
1272
assertEquals(base, ex.getURI());
1273
assertTrue(ex.getErrorCount() > 0);
1274
for (int i = 0; i < ex.getErrorCount(); i++) {
1275
assertNotNull(ex.getValidityError(i));
1276
assertTrue(ex.getLineNumber(i) >= -1);
1277
assertTrue(ex.getColumnNumber(i) >= -1);
1279
if (!xercesBroken) {
1280
Document doc = builder.build(
1281
new ByteArrayInputStream(source.getBytes("UTF-8")), base
1283
this.verify(ex.getDocument());
1284
assertEquals(doc, ex.getDocument());
1291
public void testInvalidDocFromInputStreamWithoutBase()
1292
throws IOException, ParsingException {
1294
InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
1296
validator.build(in);
1297
fail("Allowed invalid doc");
1299
catch (ValidityException ex) {
1300
assertNotNull(ex.getMessage());
1301
assertTrue(ex.getErrorCount() > 0);
1302
for (int i = 0; i < ex.getErrorCount(); i++) {
1303
assertNotNull(ex.getValidityError(i));
1304
assertTrue(ex.getLineNumber(i) >= -1);
1305
assertTrue(ex.getColumnNumber(i) >= -1);
1307
if (!xercesBroken) {
1308
Document doc = builder.build(
1309
new ByteArrayInputStream(source.getBytes("UTF-8"))
1311
this.verify(ex.getDocument());
1312
assertEquals(doc, ex.getDocument());
1319
public void testInvalidDocFromStringWithBase()
1320
throws IOException, ParsingException {
1323
validator.build(source, base);
1324
fail("Allowed invalid doc");
1326
catch (ValidityException ex) {
1327
assertNotNull(ex.getMessage());
1328
assertEquals(base, ex.getURI());
1329
assertTrue(ex.getErrorCount() > 0);
1330
for (int i = 0; i < ex.getErrorCount(); i++) {
1331
assertNotNull(ex.getValidityError(i));
1332
assertTrue(ex.getLineNumber(i) >= -1);
1333
assertTrue(ex.getColumnNumber(i) >= -1);
1335
if (!xercesBroken) {
1336
Document doc = builder.build(source, base);
1337
this.verify(ex.getDocument());
1338
assertEquals(doc, ex.getDocument());
1345
public void testInvalidDocWithCrimson()
1346
throws IOException, ParsingException {
1350
crimson = XMLReaderFactory.createXMLReader(
1351
"org.apache.crimson.parser.XMLReaderImpl");
1353
catch (SAXException ex) {
1354
// can't test Crimson if you can't load it
1357
Builder validator = new Builder(crimson, true);
1359
validator.build(source, null);
1360
fail("Allowed invalid doc");
1362
catch (ValidityException ex) {
1363
assertTrue(ex.getErrorCount() > 0);
1364
assertNull(ex.getURI());
1365
for (int i = 0; i < ex.getErrorCount(); i++) {
1366
assertNotNull(ex.getValidityError(i));
1373
public void testInvalidDocFromStringWithNullBase()
1374
throws IOException, ParsingException {
1377
validator.build(source, null);
1378
fail("Allowed invalid doc");
1380
catch (ValidityException ex) {
1381
assertTrue(ex.getErrorCount() > 0);
1382
assertNull(ex.getURI());
1383
for (int i = 0; i < ex.getErrorCount(); i++) {
1384
assertNotNull(ex.getValidityError(i));
1386
if (!xercesBroken) {
1387
Document doc = builder.build(source, null);
1388
this.verify(ex.getDocument());
1389
assertEquals(doc, ex.getDocument());
1396
public void testJavaEncodings()
1397
throws IOException, ParsingException {
1399
String str = "<?xml version='1.0' encoding='ISO8859_1'?>" +
1401
byte[] data = str.getBytes("8859_1");
1402
InputStream in = new ByteArrayInputStream(data);
1403
Document doc = builder.build(in);
1404
assertEquals("Ć©", doc.getValue());
1409
// Crimson improperly converts 0x0D and 0x0A to spaces
1410
// even when the attribute type is not CDATA.
1411
// This bug explains why the canonicalizer tests fail
1413
public void testCrimsonCharacterReferenceBug()
1414
throws IOException, ParsingException {
1417
"<!DOCTYPE test [<!ATTLIST test name ID #IMPLIED>]>"
1418
+ "<test name='
'/>";
1419
InputStream in = new ByteArrayInputStream(
1420
data.getBytes("UTF8"));
1421
Document document = builder.build(in, null);
1423
document.getRootElement().getAttributeValue("name"));
1428
public void testBaseRelativeResolution()
1429
throws IOException, ParsingException {
1430
builder.build(new File(inputDir, "baserelative/test.xml"));
1434
// make sure transcoders on input are using normalization
1435
// form C when converting from other encodings
1436
public void testNFC()
1437
throws IOException, ParsingException {
1439
Document doc = builder.build(new File(inputDir, "nfctest.xml"));
1440
Element root = doc.getRootElement();
1441
String s = root.getValue();
1442
assertEquals(1, s.length());
1443
assertEquals(0xE9, s.charAt(0));
1448
// This tests XOM's workaround for a bug in Crimson, Xerces,
1449
// and possibly other parsers
1450
public void testBaseRelativeResolutionRemotely()
1451
throws IOException, ParsingException {
1452
builder.build("http://www.cafeconleche.org");
1456
public void testExternalEntityResolution()
1457
throws IOException, ParsingException {
1459
File input = new File(inputDir, "entitytest.xml");
1460
Builder builder = new Builder(false);
1461
Document doc = builder.build(input);
1462
Element root = doc.getRootElement();
1463
Element external = root.getFirstChildElement("external");
1464
assertEquals("Hello from an entity!", external.getValue());
1469
// This test exposes a bug in Crimson but not Xerces.
1470
// It's testing whether the external DTD subset is read,
1471
// default attribute values applied, and comments and
1472
// processing instructions in the external DTD subset are not
1474
public void testExternalDTDSubset()
1475
throws IOException, ParsingException {
1477
File input = new File(inputDir, "externalDTDtest.xml");
1478
Builder builder = new Builder(false);
1479
Document doc = builder.build(input);
1480
assertEquals(2, doc.getChildCount());
1481
Element root = doc.getRootElement();
1482
Attribute name = root.getAttribute("name");
1483
assertEquals("value", name.getValue());
1484
DocType doctype = doc.getDocType();
1485
assertEquals("", doctype.getInternalDTDSubset());
1490
/* <?xml version="1.0"?>
1492
<!ELEMENT root (#PCDATA)>
1495
<!NOTATION JPEG SYSTEM "image/jpeg">
1496
<!ATTLIST root source ENTITY #REQUIRED>
1497
<!ENTITY picture SYSTEM "picture.jpg" NDATA JPEG>
1499
<root source="picture">
1500
This document is intended to test the building of
1501
various constructs in the internal DTD subset.
1504
public void testInternalDTDSubset()
1505
throws ValidityException, ParsingException, IOException {
1507
File input = new File(inputDir, "internaldtdsubsettest.xml");
1508
Builder builder = new Builder(false);
1509
Document doc = builder.build(input);
1510
String internalSubset = doc.getDocType().getInternalDTDSubset();
1511
assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
1512
assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
1513
assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
1514
assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
1515
// some confusion in the parser resolving these as relative URLs.
1516
// This is in accordance with the SAX spec, see
1517
// http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html#notationDecl(java.lang.String,%20java.lang.String,%20java.lang.String)
1518
// but how does it know the notation system ID is really a URL?
1519
assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
1520
assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
1521
assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
1522
assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
1527
public void testInternalEntityDeclDollarSign()
1528
throws ValidityException, ParsingException, IOException {
1530
String input = "<!DOCTYPE root [<!ENTITY test '$!@#$^'>] ><root />";
1531
Builder builder = new Builder(false);
1532
Document doc = builder.build(input, null);
1533
String internalSubset = doc.getDocType().getInternalDTDSubset();
1534
assertTrue(internalSubset.indexOf("<!ENTITY test \"$!@#$^\">") > 0);
1539
public void testInternalDTDSubset5To9()
1540
throws ValidityException, ParsingException, IOException {
1542
String input = "<!DOCTYPE root [<!ATTLIST root source CDATA '56789'>] ><root />";
1543
Builder builder = new Builder(false);
1544
Document doc = builder.build(input, null);
1545
String internalSubset = doc.getDocType().getInternalDTDSubset();
1546
assertTrue(internalSubset.indexOf("<!ATTLIST root source CDATA \"56789\">") > 0);
1551
public void testInternalDTDSubsetPunctuation()
1552
throws ValidityException, ParsingException, IOException {
1554
String input = "<!DOCTYPE root [<!ATTLIST root source CDATA '+,()!'>] ><root />";
1555
Builder builder = new Builder(false);
1556
Document doc = builder.build(input, null);
1557
String internalSubset = doc.getDocType().getInternalDTDSubset();
1558
assertTrue(internalSubset.indexOf("<!ATTLIST root source CDATA \"+,()!\">") > 0);
1563
/*<!ELEMENT test (#PCDATA)>
1564
<!-- comment should not be here -->
1565
<?processing instruction should not be here?>
1566
<!ATTLIST test name (CDATA) #FIXED "value">
1567
<!ATTLIST test name CDATA "value">
1568
<!ATTLIST root anattribute CDATA #REQUIRED>
1569
<!ATTLIST root anotherattribute CDATA "value">
1570
<!ENTITY hatch-pic SYSTEM "http://www.example.com/images/cup.gif" NDATA gif>
1571
<!ENTITY public-pic PUBLIC "public ID" "http://www.example.com/images/cup.gif" NDATA gif>
1572
<!ENTITY Pub-Status "This is a pre-release of the specification.">
1573
<!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
1574
<!ENTITY test SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
1575
<!NOTATION ISODATE SYSTEM "http://www.iso.ch/cate/d15903.html">
1576
<!NOTATION DATE PUBLIC "DATE PUBLIC ID" "http://www.iso.ch/cate/d15903.html">
1577
<!NOTATION gif PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"> */
1578
public void testInternalAndExternalDTDSubset()
1579
throws ValidityException, ParsingException, IOException {
1581
File input = new File(inputDir, "internalandexternaldtdsubsettest.xml");
1582
Builder builder = new Builder(false);
1583
Document doc = builder.build(input);
1584
String internalSubset = doc.getDocType().getInternalDTDSubset();
1585
assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
1586
assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
1587
assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
1588
assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
1589
assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
1590
assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
1591
assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
1592
assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
1594
assertEquals(-1, internalSubset.indexOf("comment should not be here"));
1595
assertEquals(-1, internalSubset.indexOf("processing instruction should not be here"));
1596
assertEquals(-1, internalSubset.indexOf("anattribute"));
1597
assertEquals(-1, internalSubset.indexOf("anotherattribute"));
1598
assertEquals(-1, internalSubset.indexOf("hatch-pic"));
1599
assertEquals(-1, internalSubset.indexOf("public-pic"));
1600
assertEquals(-1, internalSubset.indexOf("open-hatch"));
1601
assertEquals(-1, internalSubset.indexOf("Pub-Status-pic"));
1602
assertEquals(-1, internalSubset.indexOf("Textuality"));
1603
assertEquals(-1, internalSubset.indexOf("15903"));
1608
public void testInternalAndExternalDTDSubsetWithCrimson()
1609
throws ValidityException, ParsingException, IOException {
1613
crimson = XMLReaderFactory.createXMLReader(
1614
"org.apache.crimson.parser.XMLReaderImpl");
1616
catch (SAXException ex) {
1617
// can't test Crimson if you can't load it
1621
Builder builder = new Builder(crimson);
1622
File input = new File(inputDir, "internalandexternaldtdsubsettest.xml");
1623
Document doc = builder.build(input);
1624
String internalSubset = doc.getDocType().getInternalDTDSubset();
1625
assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
1626
assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
1627
assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
1628
assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
1629
assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
1630
assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
1631
assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
1632
assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
1634
assertEquals(-1, internalSubset.indexOf("comment should not be here"));
1635
assertEquals(-1, internalSubset.indexOf("processing instruction should not be here"));
1636
assertEquals(-1, internalSubset.indexOf("anattribute"));
1637
assertEquals(-1, internalSubset.indexOf("anotherattribute"));
1638
assertEquals(-1, internalSubset.indexOf("hatch-pic"));
1639
assertEquals(-1, internalSubset.indexOf("public-pic"));
1640
assertEquals(-1, internalSubset.indexOf("open-hatch"));
1641
assertEquals(-1, internalSubset.indexOf("Pub-Status-pic"));
1642
assertEquals(-1, internalSubset.indexOf("Textuality"));
1643
assertEquals(-1, internalSubset.indexOf("15903"));
1648
// This test exposes a bug in Crimson, Xerces 2.5 and earlier,
1649
// and possibly other parsers. I've reported the bug in Xerces,
1650
// and it is fixed in Xerces 2.6.
1651
public void testBaseRelativeResolutionRemotelyWithDirectory()
1652
throws IOException, ParsingException {
1653
builder.build("http://www.ibiblio.org/xml");
1657
// This test exposes a bug in Crimson, Xerces 2.5 and earlier,
1658
// and possibly other parsers. I've reported the bug in Xerces,
1659
// and it should be fixed in Xerces 2.6.
1660
public void testRelativeURIResolutionAgainstARedirectedBase()
1661
throws IOException, ParsingException {
1662
builder.build("http://www.ibiblio.org/xml/redirecttest.xml");
1666
public void testDontGetNodeFactory() {
1668
Builder builder = new Builder();
1669
NodeFactory factory = builder.getNodeFactory();
1670
if (factory != null) {
1672
factory.getClass().getName().endsWith("NonVerifyingFactory")
1679
public void testGetNodeFactory() {
1680
NodeFactory factory = new NodeFactory();
1681
Builder builder = new Builder(factory);
1682
assertEquals(factory, builder.getNodeFactory());
1686
// Make sure additional namespaces aren't added for
1687
// attributes. This test is flaky because it assumes
1688
// the parser reports attributes in the correct order,
1689
// which is not guaranteed. I use a custom SAX Filter to
1690
// make sure the namespace declaration comes before the attribute.
1691
public void testAttributesVsNamespaces()
1692
throws ParsingException, IOException, SAXException {
1694
XMLFilter filter = new OrderingFilter();
1696
XMLReaderFactory.createXMLReader(
1697
"org.apache.xerces.parsers.SAXParser"
1700
Builder builder = new Builder(filter);
1701
String data ="<a/>";
1702
Document doc = builder.build(data, null);
1703
Element root = doc.getRootElement();
1704
root.removeAttribute(root.getAttribute(0));
1705
assertNull(root.getNamespaceURI("pre"));
1710
private static class OrderingFilter extends XMLFilterImpl {
1712
public void startElement(String namespaceURI, String localName,
1713
String qualifiedName, Attributes atts) throws SAXException {
1715
AttributesImpl newAttributes = new AttributesImpl();
1716
newAttributes.addAttribute(
1721
"http://www.example.com/");
1722
newAttributes.addAttribute(
1723
"http://www.example.com/",
1728
super.startElement(namespaceURI, localName, qualifiedName,
1735
public void testValidateMalformedDocument()
1736
throws IOException {
1738
Reader reader = new StringReader("<!DOCTYPE root [" +
1739
"<!ELEMENT root (a, b)>" +
1740
"<!ELEMENT a (EMPTY)>" +
1741
"<!ELEMENT b (PCDATA)>" +
1742
"]><root><a/><b></b>");
1744
validator.build(reader);
1745
fail("Allowed malformed doc");
1747
catch (ValidityException ex) {
1748
fail("Threw validity error instead of well-formedness error");
1750
catch (ParsingException ex) {
1751
assertNotNull(ex.getMessage());
1752
assertNull(ex.getURI());
1758
/* Test for particular bug in Crimson with mixed content declarations */
1759
public void testBuildInternalDTDSubsetWithCrimson()
1760
throws ParsingException, IOException {
1762
String dtd = " <!ELEMENT doc (#PCDATA|a)*>\n";
1764
String document = "<!DOCTYPE a [\n" + dtd + "]>\n<a/>";
1767
crimson = XMLReaderFactory.createXMLReader(
1768
"org.apache.crimson.parser.XMLReaderImpl");
1770
catch (SAXException ex) {
1771
// can't test Crimson if you can't load it
1775
Builder builder = new Builder(crimson);
1776
Document doc = builder.build(document, null);
1778
String parsedDTD = doc.getDocType().getInternalDTDSubset();
1779
assertEquals(dtd, parsedDTD);
1784
/* Test for particular bug in Crimson with mixed content declarations */
1785
public void testBuildXMLNamespaceDeclarationWithCrimson()
1786
throws ParsingException, IOException {
1788
String document = "<doc xmlns:xml='http://www.w3.org/XML/1998/namespace' />";
1791
crimson = XMLReaderFactory.createXMLReader(
1792
"org.apache.crimson.parser.XMLReaderImpl");
1794
catch (SAXException ex) {
1795
// can't test Crimson if you can't load it
1799
Builder builder = new Builder(crimson);
1800
Document doc = builder.build(document, null);
1802
assertEquals("<doc />", doc.getRootElement().toXML());
1807
public void testBuildIllegalXMLNamespaceDeclarationWithCrimson()
1808
throws ParsingException, IOException {
1810
String document = "<doc xmlns:xml='http://www.w3.org/XML/2005/namespace' />";
1813
crimson = XMLReaderFactory.createXMLReader(
1814
"org.apache.crimson.parser.XMLReaderImpl");
1816
catch (SAXException ex) {
1817
// can't test Crimson if you can't load it
1821
Builder builder = new Builder(crimson);
1823
builder.build(document, null);
1824
fail("Allowed wrong namespace URI for xml prefix");
1826
catch (ParsingException success) {
1827
assertNotNull(success.getMessage());
1833
public void testATTLISTDeclaresXMLSpacePreserveOnlyWithCrimson()
1834
throws ParsingException, IOException {
1836
String dtd = "<!DOCTYPE a [<!ATTLIST doc xml:space (preserve) 'preserve'>]\n>";
1838
String data = dtd + "<doc />";
1841
crimson = XMLReaderFactory.createXMLReader(
1842
"org.apache.crimson.parser.XMLReaderImpl");
1844
catch (SAXException ex) {
1845
// can't test Crimson if you can't load it
1849
Builder builder = new Builder(crimson);
1850
Document doc = builder.build(data, null);
1851
assertEquals(1, doc.getRootElement().getAttributeCount());
1856
public void testNoInternalSubsetWithCrimson()
1857
throws ParsingException, IOException {
1861
crimson = XMLReaderFactory.createXMLReader(
1862
"org.apache.crimson.parser.XMLReaderImpl");
1864
catch (SAXException ex) {
1865
// can't test Crimson if you can't load it
1869
File input = new File(inputDir, "externalDTDtest.xml");
1870
Builder builder = new Builder(crimson);
1871
Document doc = builder.build(input);
1872
String subset = doc.getDocType().getInternalDTDSubset();
1873
assertEquals("", subset);
1878
public void testValidateMalformedDocumentWithCrimson()
1879
throws IOException {
1881
Reader reader = new StringReader("<!DOCTYPE root [" +
1882
"<!ELEMENT root (a, b)>" +
1883
"<!ELEMENT a (EMPTY)>" +
1884
"<!ELEMENT b (PCDATA)>" +
1885
"]><root><a/><b></b>");
1888
crimson = XMLReaderFactory.createXMLReader(
1889
"org.apache.crimson.parser.XMLReaderImpl");
1891
catch (SAXException ex) {
1892
// can't test Crimson if you can't load it
1895
Builder validator = new Builder(crimson, true);
1897
validator.build(reader);
1898
fail("Allowed malformed doc");
1900
catch (ValidityException ex) {
1901
fail("Crimson threw validity error instead of well-formedness error");
1903
catch (ParsingException success) {
1904
assertNotNull(success.getMessage());
1905
assertNull(success.getURI());
1911
// This is testing a work-around for a Xerces bug
1912
// http://nagoya.apache.org/bugzilla/show_bug.cgi?id=27583
1913
// that reports this as an IOException rather than a SAXException
1914
public void testBuildMalformedDocumentWithUnpairedSurrogate()
1915
throws IOException {
1917
String doc = "<doc>A\uD800A</doc>";
1919
builder.build(doc, "http://www.example.com");
1920
fail("Allowed malformed doc");
1922
catch (ParsingException success) {
1923
assertNotNull(success.getMessage());
1924
assertEquals("http://www.example.com/", success.getURI());
1930
public void testBuildMalformedDocumentWithBadUnicodeData()
1931
throws IOException {
1933
File f = new File(inputDir, "xmlconf");
1934
f = new File(f, "xmltest");
1935
f = new File(f, "not-wf");
1936
f = new File(f, "sa");
1937
f = new File(f, "170.xml");
1941
fail("Allowed malformed doc");
1943
catch (ParsingException success) {
1944
assertNotNull(success.getMessage());
1945
assertTrue(success.getURI().endsWith(
1946
"data/xmlconf/xmltest/not-wf/sa/170.xml"));
1947
assertTrue(success.getURI().startsWith("file:/"));
1954
public void testBuildAnotherMalformedDocumentWithBadUnicodeData()
1955
throws IOException {
1957
String filename = "data/oasis/p02fail30.xml";
1958
File f = new File(inputDir, "oasis");
1959
f = new File(f, "p02fail30.xml");
1963
fail("Allowed malformed doc");
1965
catch (ParsingException success) {
1966
assertNotNull(success.getMessage());
1967
assertTrue(success.getURI().endsWith(filename));
1968
assertTrue(success.getURI().startsWith("file:/"));
1975
public void testBuildMalformedDocumentWithBadParser()
1976
throws ParsingException, IOException {
1979
XMLReader parser = new CustomReader();
1980
Builder builder = new Builder(parser);
1981
builder.build("http://www.example.org/");
1982
fail("built from bad data");
1984
catch (ParsingException success) {
1985
assertNotNull(success.getMessage());
1986
assertTrue(success.getCause() instanceof WellformednessException);
1992
public void testBuildMalformedDocumentWithCrimson()
1993
throws IOException {
1995
Reader reader = new StringReader("<!DOCTYPE root [" +
1996
"<!ELEMENT root (a, b)>" +
1997
"<!ELEMENT a (EMPTY)>" +
1998
"<!ELEMENT b (PCDATA)>" +
1999
"]><root><a/><b></b>");
2002
crimson = XMLReaderFactory.createXMLReader(
2003
"org.apache.crimson.parser.XMLReaderImpl");
2005
catch (SAXException ex) {
2006
// can't test Crimson if you can't load it
2009
Builder builder = new Builder(crimson);
2011
builder.build(reader);
2012
fail("Allowed malformed doc");
2014
catch (ValidityException ex) {
2015
fail("Crimson threw validity error instead of well-formedness error");
2017
catch (ParsingException ex) {
2018
assertNotNull(ex.getMessage());
2019
assertNull(ex.getURI());
2025
public void testNestedExceptionWithSAXParseException()
2026
throws IOException {
2028
Reader reader = new StringReader("<root ");
2029
Builder builder = new Builder();
2031
builder.build(reader);
2032
fail("Allowed malformed doc");
2034
catch (ValidityException ex) {
2035
fail("Parser threw validity error instead of well-formedness error");
2037
catch (ParsingException ex) {
2038
assertNotNull(ex.getCause());
2044
public void testBuildFunkyNamespacesWithUntrustedParser()
2045
throws ParsingException, IOException, SAXException {
2047
Reader reader = new StringReader(
2048
"<root xmlns='http://example.org/'>" +
2049
"<pre:a xmlns:pre='http://www.root.org/' " +
2050
"xmlns='http://www.red.com'>" +
2053
XMLReader parser = XMLReaderFactory.createXMLReader(
2054
"org.apache.xerces.parsers.SAXParser");
2055
XMLFilter filter = new XMLFilterImpl();
2056
filter.setParent(parser);
2057
Builder builder = new Builder(filter);
2058
Document doc = builder.build(reader);
2059
Element root = doc.getRootElement();
2060
Element prea = (Element) root.getChild(0);
2061
Element b = (Element) prea.getChild(0);
2062
assertEquals("http://www.red.com", b.getNamespaceURI());
2067
// from XML Conformance Test Suite; James Clark test
2069
public void testLineBreaksInInternalDTDSubset()
2070
throws ParsingException, IOException {
2072
Document doc = builder.build(new File(inputDir, "097.xml"));
2073
String expectedResult = "<?xml version=\"1.0\"?>\n"
2074
+ "<!DOCTYPE doc [\n"
2075
+ " <!ELEMENT doc (#PCDATA)>\n"
2076
+ " <!ENTITY % e SYSTEM \"097.ent\">\n"
2077
+ " <!ATTLIST doc a1 CDATA \"v1\">\n"
2078
+ " <!ATTLIST doc a2 CDATA #IMPLIED>\n"
2080
+ "<doc a1=\"v1\" />\n";
2081
String actual = doc.toXML();
2082
assertEquals(expectedResult, actual);
2087
public void testBuildDocumentThatUndeclaresDefaultNamespace()
2088
throws ParsingException, IOException {
2090
Document doc = builder.build(new File(inputDir, "undeclare.xml"));
2091
String expectedResult = "<?xml version=\"1.0\"?>\n"
2092
+ "<root xmlns=\"http://www.example.org\" "
2093
+ "xmlns:pre=\"http://www.red.com/\" test=\"test\" "
2094
+ "pre:red=\"value\">some data<something xmlns=\"\" />"
2096
String actual = doc.toXML();
2097
assertEquals(expectedResult, actual);
2102
public void testBuildFromFileThatContainsNonASCIICharacterInName()
2103
throws ParsingException, IOException {
2105
File f = new File(inputDir, "resumƩ.xml");
2107
Writer out = new OutputStreamWriter(
2108
new FileOutputStream(f), "UTF8");
2109
out.write("<resumƩ />");
2112
Document doc = builder.build(f);
2113
String expectedResult = "<?xml version=\"1.0\"?>\n"
2115
String actual = doc.toXML();
2116
assertEquals(expectedResult, actual);
2117
assertTrue(doc.getBaseURI().startsWith("file:/"));
2118
assertTrue(doc.getBaseURI().endsWith("data/resum%C3%A9.xml"));
2121
if (f.exists()) f.delete();
2127
// This test fails on Mac OS X. It passes on Linux.
2128
public void testBuildFromFileThatContainsPlane1CharacterInName()
2129
throws ParsingException, IOException {
2131
int gclef = 0x1D120;
2132
char high = (char) ((gclef - 0x10000)/0x400 + 0xD800);
2133
char low = (char) ((gclef - 0x10000) % 0x400 + 0xDC00);
2134
File f = new File(inputDir, "music" + high + "" + low + ".xml");
2136
Writer out = new OutputStreamWriter(
2137
new FileOutputStream(f), "UTF8");
2138
out.write("<resumƩ />");
2141
Document doc = builder.build(f);
2142
String expectedResult = "<?xml version=\"1.0\"?>\n"
2144
String actual = doc.toXML();
2145
assertEquals(expectedResult, actual);
2148
if (f.exists()) f.delete();
2154
private File makeFile(String name) throws IOException {
2156
File f = new File(inputDir, "" + name);
2157
Writer out = new OutputStreamWriter(
2158
new FileOutputStream(f), "UTF8");
2159
out.write("<data/>");
2167
public void testBuildFromFileThatContainsAmpersandInName()
2168
throws ParsingException, IOException {
2170
Document doc = builder.build(new File(inputDir, "&file.xml"));
2171
String expectedResult = "<?xml version=\"1.0\"?>\n"
2173
String actual = doc.toXML();
2174
assertEquals(expectedResult, actual);
2175
assertTrue(doc.getBaseURI().startsWith("file:/"));
2176
assertTrue(doc.getBaseURI().endsWith("data/&file.xml"));
2181
public void testBuildFromFileThatContainsSpaceInName()
2182
throws ParsingException, IOException {
2184
File f = makeFile("space file.xml");
2185
Document doc = builder.build(f);
2186
String expectedResult = "<?xml version=\"1.0\"?>\n"
2188
String actual = doc.toXML();
2190
assertEquals(expectedResult, actual);
2191
assertTrue(doc.getBaseURI().startsWith("file:/"));
2192
assertTrue(doc.getBaseURI().endsWith("data/space%"
2193
+ Integer.toHexString(' ') + "file.xml"));
2198
public void testBuildFromFileThatContainsSharpInName()
2199
throws ParsingException, IOException {
2201
File f = new File(inputDir, "#file.xml");
2203
Writer out = new OutputStreamWriter(
2204
new FileOutputStream(f), "UTF8");
2205
out.write("<data />");
2208
Document doc = builder.build(f);
2209
String expectedResult = "<?xml version=\"1.0\"?>\n"
2211
String actual = doc.toXML();
2212
assertEquals(expectedResult, actual);
2213
assertTrue(doc.getBaseURI().startsWith("file:/"));
2214
assertTrue(doc.getBaseURI().endsWith("data/%23file.xml"));
2217
if (f.exists()) f.delete();
2223
public void testBuildFromFileThatContainsExclamationPointInName()
2224
throws ParsingException, IOException {
2226
Document doc = builder.build(new File(inputDir, "!file.xml"));
2227
String expectedResult = "<?xml version=\"1.0\"?>\n"
2229
String actual = doc.toXML();
2230
assertEquals(expectedResult, actual);
2231
assertTrue(doc.getBaseURI().startsWith("file:/"));
2232
assertTrue(doc.getBaseURI().endsWith("data/!file.xml"));
2237
public void testBuildFromFileThatContainsDoubleQuoteInName()
2238
throws ParsingException, IOException {
2240
File f = makeFile("\"file\".xml");
2242
Document doc = builder.build(f);
2244
String expectedResult = "<?xml version=\"1.0\"?>\n<data />\n";
2245
String actual = doc.toXML();
2246
assertEquals(expectedResult, actual);
2247
assertTrue(doc.getBaseURI().startsWith("file:/"));
2248
assertTrue(doc.getBaseURI().endsWith("data/%22file%22.xml"));
2250
catch (FileNotFoundException ex) {
2251
// This platform doesn't allow double quotes in file names
2257
public void testBuildFromFileThatContainsSingleQuoteInName()
2258
throws ParsingException, IOException {
2260
File f = makeFile("'file'.xml");
2261
Document doc = builder.build(f);
2263
String expectedResult = "<?xml version=\"1.0\"?>\n"
2265
String actual = doc.toXML();
2266
assertEquals(expectedResult, actual);
2267
assertTrue(doc.getBaseURI().startsWith("file:/"));
2268
assertTrue(doc.getBaseURI().endsWith("data/'file'.xml"));
2273
public void testBuildFromFileThatContainsParenthesesInName()
2274
throws ParsingException, IOException {
2276
Document doc = builder.build(new File(inputDir, "()file.xml"));
2277
String expectedResult = "<?xml version=\"1.0\"?>\n"
2279
String actual = doc.toXML();
2280
assertEquals(expectedResult, actual);
2281
assertTrue(doc.getBaseURI().startsWith("file:/"));
2282
assertTrue(doc.getBaseURI().endsWith("data/()file.xml"));
2287
public void testBuildFromFileThatContainsCurlyBracesInName()
2288
throws ParsingException, IOException {
2290
Document doc = builder.build(new File(inputDir, "{file}.xml"));
2291
String expectedResult = "<?xml version=\"1.0\"?>\n"
2293
String actual = doc.toXML();
2294
assertEquals(expectedResult, actual);
2295
assertTrue(doc.getBaseURI().startsWith("file:/"));
2296
assertTrue(doc.getBaseURI().endsWith("data/%"
2297
+ Integer.toHexString('{').toUpperCase() + "file%"
2298
+ Integer.toHexString('}').toUpperCase() + ".xml"));
2303
public void testBuildFromFileThatContainsSquareBracketsInName()
2304
throws ParsingException, IOException {
2306
Document doc = builder.build(new File(inputDir, "[file].xml"));
2307
String expectedResult = "<?xml version=\"1.0\"?>\n"
2309
String actual = doc.toXML();
2310
assertEquals(expectedResult, actual);
2311
assertTrue(doc.getBaseURI().startsWith("file:/"));
2312
assertTrue(doc.getBaseURI().endsWith("data/%"
2313
+ Integer.toHexString('[').toUpperCase() + "file%"
2314
+ Integer.toHexString(']').toUpperCase() + ".xml"));
2319
public void testBuildFromFileThatContainsVerticalBarInName()
2320
throws ParsingException, IOException {
2322
File f = makeFile("|file.xml");
2324
Document doc = builder.build(f);
2326
String expectedResult = "<?xml version=\"1.0\"?>\n"
2328
String actual = doc.toXML();
2329
assertEquals(expectedResult, actual);
2330
assertTrue(doc.getBaseURI().startsWith("file:/"));
2331
assertTrue(doc.getBaseURI().endsWith("data/%"
2332
+ Integer.toHexString('|').toUpperCase()
2335
catch (FileNotFoundException ex) {
2336
// This platform doesn't allow vertical bars in file names
2342
public void testBuildFromFileThatContainsColonInName()
2343
throws ParsingException, IOException {
2345
File f = makeFile(":file.xml");
2347
Document doc = builder.build(f);
2349
String expectedResult = "<?xml version=\"1.0\"?>\n"
2351
String actual = doc.toXML();
2352
assertEquals(expectedResult, actual);
2353
assertTrue(doc.getBaseURI().startsWith("file:/"));
2354
assertTrue(doc.getBaseURI().endsWith("data/:file.xml"));
2356
catch (FileNotFoundException ex) {
2357
// This platform doesn't allow colons in file names
2363
public void testBuildFromFileThatContainsUnderscoreInName()
2364
throws ParsingException, IOException {
2366
File f = makeFile("_file.xml");
2367
Document doc = builder.build(f);
2369
String expectedResult = "<?xml version=\"1.0\"?>\n"
2371
String actual = doc.toXML();
2372
assertEquals(expectedResult, actual);
2373
assertTrue(doc.getBaseURI().startsWith("file:/"));
2374
assertTrue(doc.getBaseURI().endsWith("data/_file.xml"));
2379
public void testBuildFromFileThatContainsUppercaseASCIIInName()
2380
throws ParsingException, IOException {
2382
File f = makeFile("ABCDEFGHIJKLMONPQRSTUVWXYZ.xml");
2383
Document doc = builder.build(f);
2385
String expectedResult = "<?xml version=\"1.0\"?>\n"
2387
String actual = doc.toXML();
2388
assertEquals(expectedResult, actual);
2389
assertTrue(doc.getBaseURI().startsWith("file:/"));
2390
assertTrue(doc.getBaseURI().endsWith("data/ABCDEFGHIJKLMONPQRSTUVWXYZ.xml"));
2395
public void testBuildFromFileThatContainsAsteriskInName()
2396
throws ParsingException, IOException {
2398
File f = makeFile("*file.xml");
2400
Document doc = builder.build(f);
2402
String expectedResult = "<?xml version=\"1.0\"?>\n"
2404
String actual = doc.toXML();
2405
assertEquals(expectedResult, actual);
2406
assertTrue(doc.getBaseURI().startsWith("file:/"));
2407
assertTrue(doc.getBaseURI().endsWith("data/*file.xml"));
2409
catch (FileNotFoundException ex) {
2410
// This platform doesn't allow asterisks in file names
2416
public void testBuildFromFileThatContainsSemicolonInName()
2417
throws ParsingException, IOException {
2419
Document doc = builder.build(new File(inputDir, ";file.xml"));
2420
String expectedResult = "<?xml version=\"1.0\"?>\n"
2422
String actual = doc.toXML();
2423
assertEquals(expectedResult, actual);
2424
assertTrue(doc.getBaseURI().startsWith("file:/"));
2425
assertTrue(doc.getBaseURI().endsWith("data/;file.xml"));
2430
public void testBuildFromFileThatContainsPlusSignInName()
2431
throws ParsingException, IOException {
2433
Document doc = builder.build(new File(inputDir, "+file.xml"));
2434
String expectedResult = "<?xml version=\"1.0\"?>\n"
2436
String actual = doc.toXML();
2437
assertEquals(expectedResult, actual);
2438
assertTrue(doc.getBaseURI().startsWith("file:/"));
2439
assertTrue(doc.getBaseURI().endsWith("data/%"
2440
+ Integer.toHexString('+').toUpperCase() + "file.xml"));
2445
public void testBuildFromFileThatContainsCommaInName()
2446
throws ParsingException, IOException {
2448
File f = new File(inputDir, ",file.xml");
2450
Writer out = new OutputStreamWriter(
2451
new FileOutputStream(f), "UTF8");
2452
out.write("<data />");
2455
Document doc = builder.build(f);
2456
String expectedResult = "<?xml version=\"1.0\"?>\n"
2458
String actual = doc.toXML();
2459
assertEquals(expectedResult, actual);
2460
assertTrue(doc.getBaseURI().startsWith("file:/"));
2461
assertTrue(doc.getBaseURI().endsWith("data/,file.xml"));
2464
if (f.exists()) f.delete();
2470
public void testBuildFromFileThatContainsBackslashInName()
2471
throws ParsingException, IOException {
2473
String os = System.getProperty("os.name", "Unix");
2474
if (os.indexOf("Windows") >= 0) return;
2476
File f = new File(inputDir, "\\file.xml");
2478
Writer out = new OutputStreamWriter(
2479
new FileOutputStream(f), "UTF8");
2480
out.write("<data />");
2483
Document doc = builder.build(f);
2484
String expectedResult = "<?xml version=\"1.0\"?>\n"
2486
String actual = doc.toXML();
2487
assertEquals(expectedResult, actual);
2488
assertTrue(doc.getBaseURI().startsWith("file:/"));
2489
assertTrue(doc.getBaseURI().endsWith("data/%5Cfile.xml"));
2492
if (f.exists()) f.delete();
2498
public void testBuildFromFileThatContainsC0ControlCharacterInName()
2499
throws ParsingException, IOException {
2501
File f = new File(inputDir, "\u0019file.xml");
2503
Writer out = new OutputStreamWriter(
2504
new FileOutputStream(f), "UTF8");
2505
out.write("<data />");
2508
Document doc = builder.build(f);
2509
String expectedResult = "<?xml version=\"1.0\"?>\n"
2511
String actual = doc.toXML();
2512
assertEquals(expectedResult, actual);
2513
assertTrue(doc.getBaseURI().startsWith("file:/"));
2514
assertTrue(doc.getBaseURI().endsWith("data/%19file.xml"));
2516
catch (FileNotFoundException ex) {
2517
// This platform doesn't allow C0 controls in file names
2520
if (f.exists()) f.delete();
2526
public void testBuildFromFileThatContainsTabCharacterInName()
2527
throws ParsingException, IOException {
2529
File f = new File(inputDir, "\tfile.xml");
2531
Writer out = new OutputStreamWriter(
2532
new FileOutputStream(f), "UTF8");
2533
out.write("<data />");
2536
Document doc = builder.build(f);
2537
String expectedResult = "<?xml version=\"1.0\"?>\n"
2539
String actual = doc.toXML();
2540
assertEquals(expectedResult, actual);
2541
assertTrue(doc.getBaseURI().startsWith("file:/"));
2542
assertTrue(doc.getBaseURI().endsWith("data/%09file.xml"));
2544
catch (FileNotFoundException ex) {
2545
// This platform doesn't allow tabs in file names
2548
if (f.exists()) f.delete();
2554
public void testBuildFromFileThatContainsTildeInName()
2555
throws ParsingException, IOException {
2557
File f = new File(inputDir, "~file.xml");
2559
Writer out = new OutputStreamWriter(
2560
new FileOutputStream(f), "UTF8");
2561
out.write("<data />");
2564
Document doc = builder.build(f);
2565
String expectedResult = "<?xml version=\"1.0\"?>\n"
2567
String actual = doc.toXML();
2568
assertEquals(expectedResult, actual);
2569
assertTrue(doc.getBaseURI().startsWith("file:/"));
2570
assertTrue(doc.getBaseURI().endsWith("data/~file.xml"));
2573
if (f.exists()) f.delete();
2579
public void testBuildFromFileThatContainsAngleBracketsInName()
2580
throws ParsingException, IOException {
2582
File f = makeFile("<file>.xml");
2584
Document doc = builder.build(f);
2586
String expectedResult = "<?xml version=\"1.0\"?>\n"
2588
String actual = doc.toXML();
2589
assertEquals(expectedResult, actual);
2590
assertTrue(doc.getBaseURI().startsWith("file:/"));
2591
assertTrue(doc.getBaseURI().endsWith("data/%"
2592
+ Integer.toHexString('<').toUpperCase() + "file%"
2593
+ Integer.toHexString('>').toUpperCase() + ".xml"));
2595
catch (FileNotFoundException ex) {
2596
// This platform doesn't allow < and > in file names
2602
public void testBuildFromFileThatContainsDollarSignInName()
2603
throws ParsingException, IOException {
2605
Document doc = builder.build(new File(inputDir, "$file.xml"));
2606
String expectedResult = "<?xml version=\"1.0\"?>\n"
2608
String actual = doc.toXML();
2609
assertEquals(expectedResult, actual);
2610
assertTrue(doc.getBaseURI().startsWith("file:/"));
2611
assertTrue(doc.getBaseURI().endsWith("data/$file.xml"));
2616
public void testBuildFromFileThatContainsPercentSignInName()
2617
throws ParsingException, IOException {
2619
Document doc = builder.build(new File(inputDir, "%file.xml"));
2620
String expectedResult = "<?xml version=\"1.0\"?>\n"
2622
String actual = doc.toXML();
2623
assertEquals(expectedResult, actual);
2624
assertTrue(doc.getBaseURI().startsWith("file:/"));
2625
assertTrue(doc.getBaseURI().endsWith("data/%"
2626
+ Integer.toHexString('%') + "file.xml"));
2631
public void testBuildFromFileThatContainsQuestionMarkInName()
2632
throws ParsingException, IOException {
2634
File f = makeFile("?file.xml");
2636
Document doc = builder.build(f);
2638
String expectedResult = "<?xml version=\"1.0\"?>\n"
2640
String actual = doc.toXML();
2641
assertEquals(expectedResult, actual);
2642
assertTrue(doc.getBaseURI().startsWith("file:/"));
2643
assertTrue(doc.getBaseURI().endsWith("data/%"
2644
+ Integer.toHexString('?').toUpperCase() + "file.xml"));
2646
catch (FileNotFoundException ex) {
2647
// This platform doesn't allow question marks in file names
2653
public void testBuildFromFileThatContainsAtSignInName()
2654
throws ParsingException, IOException {
2656
Document doc = builder.build(new File(inputDir, "@file.xml"));
2657
String expectedResult = "<?xml version=\"1.0\"?>\n"
2659
String actual = doc.toXML();
2660
assertEquals(expectedResult, actual);
2661
assertTrue(doc.getBaseURI().startsWith("file:/"));
2662
assertTrue(doc.getBaseURI().endsWith("data/%"
2663
+ Integer.toHexString('@') + "file.xml"));
2668
public void testBuildFromFileThatContainsEqualsSignInName()
2669
throws ParsingException, IOException {
2671
Document doc = builder.build(new File(inputDir, "=file.xml"));
2672
String expectedResult = "<?xml version=\"1.0\"?>\n"
2674
String actual = doc.toXML();
2675
assertEquals(expectedResult, actual);
2676
assertTrue(doc.getBaseURI().startsWith("file:/"));
2677
assertTrue(doc.getBaseURI().endsWith("data/=file.xml"));
2682
public void testBuildFromFileThatContainsCaretInName()
2683
throws ParsingException, IOException {
2685
Document doc = builder.build(new File(inputDir, "^file.xml"));
2686
String expectedResult = "<?xml version=\"1.0\"?>\n"
2688
String actual = doc.toXML();
2689
assertEquals(expectedResult, actual);
2690
assertTrue(doc.getBaseURI().startsWith("file:/"));
2691
assertTrue(doc.getBaseURI().endsWith("data/%"
2692
+ Integer.toHexString('^').toUpperCase() + "file.xml"));
2697
public void testBuildFromFileThatContainsBactickInName()
2698
throws ParsingException, IOException {
2700
Document doc = builder.build(new File(inputDir, "`file.xml"));
2701
String expectedResult = "<?xml version=\"1.0\"?>\n"
2703
String actual = doc.toXML();
2704
assertEquals(expectedResult, actual);
2705
assertTrue(doc.getBaseURI().startsWith("file:/"));
2706
assertTrue(doc.getBaseURI().endsWith("data/%"
2707
+ Integer.toHexString('`') + "file.xml"));
2712
private static class NonValidatingFilter extends XMLFilterImpl {
2714
public void setFeature(String uri, boolean value)
2715
throws SAXNotRecognizedException, SAXNotSupportedException {
2717
if ("http://xml.org/sax/features/validation".equals(uri) && value) {
2718
throw new SAXNotSupportedException("");
2720
super.setFeature(uri, value);
2724
public boolean getFeature(String uri)
2725
throws SAXNotRecognizedException, SAXNotSupportedException {
2727
if ("http://xml.org/sax/features/validation".equals(uri)) {
2730
return super.getFeature(uri);
2738
public void testNonValidatingParserException() throws SAXException {
2740
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
2741
XMLFilter filter = new NonValidatingFilter();
2742
filter.setParent(parser);
2745
new Builder(filter, true, null);
2746
fail("Validating with a non-validating parser");
2748
catch (XMLException success) {
2749
assertNotNull(success.getMessage());
2754
private static class NonEntityResolvingFilter extends XMLFilterImpl {
2756
public void setFeature(String uri, boolean value)
2757
throws SAXNotRecognizedException, SAXNotSupportedException {
2760
"http://xml.org/sax/features/validation".equals(uri)
2761
|| "http://xml.org/sax/features/external-general-entities".equals(uri))
2762
|| "http://xml.org/sax/features/external-parameter-entities".equals(uri)) {
2763
throw new SAXNotSupportedException("");
2765
super.setFeature(uri, value);
2769
public boolean getFeature(String uri)
2770
throws SAXNotRecognizedException, SAXNotSupportedException {
2772
if ("http://xml.org/sax/features/validation".equals(uri)
2773
|| "http://xml.org/sax/features/external-general-entities".equals(uri)
2774
|| "http://xml.org/sax/features/external-parameter-entities".equals(uri)) {
2777
return super.getFeature(uri);
2785
public void testNonEntityResolvingParserException() throws SAXException {
2787
XMLReader parser = XMLReaderFactory.createXMLReader(
2788
"org.apache.xerces.parsers.SAXParser");
2789
XMLFilter filter = new NonEntityResolvingFilter();
2790
filter.setParent(parser);
2793
new Builder(filter, false, null);
2794
fail("Accepted a non-entity resolving parser");
2796
catch (XMLException success) {
2797
assertNotNull(success.getMessage());
2803
// Fake certain errors to test workarounds for bugs in certain
2804
// parsers, especially Piccolo.
2805
private static class ExceptionTester extends XMLFilterImpl {
2807
private Exception ex;
2809
ExceptionTester(Exception ex) {
2813
public void parse(InputSource in) throws IOException, SAXException {
2814
if (ex instanceof IOException) throw (IOException) ex;
2815
else if (ex instanceof SAXException) throw (SAXException) ex;
2816
else throw (RuntimeException) ex;
2822
public void testParserThrowsNullPointerException()
2823
throws SAXException, IOException {
2825
XMLReader parser = XMLReaderFactory.createXMLReader(
2826
"org.apache.xerces.parsers.SAXParser");
2827
Exception cause = new NullPointerException();
2828
XMLFilter filter = new ExceptionTester(cause);
2829
filter.setParent(parser);
2830
Builder builder = new Builder(filter);
2833
builder.build("<data/>");
2835
catch (ParsingException success) {
2836
assertEquals(cause, success.getCause());
2842
public void testParserThrowsNegativeArraySizeException()
2843
throws SAXException, IOException {
2845
XMLReader parser = XMLReaderFactory.createXMLReader(
2846
"org.apache.xerces.parsers.SAXParser");
2847
Exception cause = new NegativeArraySizeException();
2848
XMLFilter filter = new ExceptionTester(cause);
2849
filter.setParent(parser);
2850
Builder builder = new Builder(filter);
2853
builder.build("<data/>");
2855
catch (ParsingException success) {
2856
assertEquals(cause, success.getCause());
2862
public void testParserThrowsArrayIndexOutOfBoundsException()
2863
throws SAXException, IOException {
2865
XMLReader parser = XMLReaderFactory.createXMLReader(
2866
"org.apache.xerces.parsers.SAXParser");
2867
Exception cause = new ArrayIndexOutOfBoundsException();
2868
XMLFilter filter = new ExceptionTester(cause);
2869
filter.setParent(parser);
2870
Builder builder = new Builder(filter);
2873
builder.build("<data/>");
2875
catch (ParsingException success) {
2876
assertEquals(cause, success.getCause());
2882
public void testParserThrowsUTFDataFormatException()
2883
throws SAXException, IOException {
2885
XMLReader parser = XMLReaderFactory.createXMLReader(
2886
"org.apache.xerces.parsers.SAXParser");
2887
Exception cause = new UTFDataFormatException();
2888
XMLFilter filter = new ExceptionTester(cause);
2889
filter.setParent(parser);
2890
Builder builder = new Builder(filter);
2893
builder.build("<data/>");
2895
catch (ParsingException success) {
2896
assertEquals(cause, success.getCause());
2902
public void testParserThrowsCharConversionException()
2903
throws SAXException, IOException {
2905
XMLReader parser = XMLReaderFactory.createXMLReader(
2906
"org.apache.xerces.parsers.SAXParser");
2907
Exception cause = new CharConversionException();
2908
XMLFilter filter = new ExceptionTester(cause);
2909
filter.setParent(parser);
2910
Builder builder = new Builder(filter);
2913
builder.build("<data/>");
2915
catch (ParsingException success) {
2916
assertEquals(cause, success.getCause());
2922
public void testParserThrowsPlainSAXException()
2923
throws SAXException, IOException {
2925
XMLReader parser = XMLReaderFactory.createXMLReader(
2926
"org.apache.xerces.parsers.SAXParser");
2927
Exception cause = new SAXException("What happened to no-args constructor?");
2928
XMLFilter filter = new ExceptionTester(cause);
2929
filter.setParent(parser);
2930
Builder builder = new Builder(filter);
2933
builder.build("<data/>");
2935
catch (ParsingException success) {
2936
assertEquals(cause, success.getCause());
2942
public void testParserThrowsUnexpectedRuntimeException()
2943
throws SAXException, IOException {
2945
XMLReader parser = XMLReaderFactory.createXMLReader(
2946
"org.apache.xerces.parsers.SAXParser");
2947
Exception cause = new RuntimeException();
2948
XMLFilter filter = new ExceptionTester(cause);
2949
filter.setParent(parser);
2950
Builder builder = new Builder(filter);
2953
builder.build("<data/>");
2955
catch (ParsingException success) {
2956
assertEquals(cause, success.getCause());
2962
public void testParserThrowsIOException()
2963
throws SAXException, ParsingException {
2965
XMLReader parser = XMLReaderFactory.createXMLReader(
2966
"org.apache.xerces.parsers.SAXParser");
2967
Exception cause = new IOException();
2968
XMLFilter filter = new ExceptionTester(cause);
2969
filter.setParent(parser);
2970
Builder builder = new Builder(filter);
2973
builder.build("<data/>");
2975
catch (IOException success) {
2976
assertEquals(cause, success);
2982
public void testCrimsonIgnoresWarning()
2983
throws SAXException, ParsingException, IOException {
2988
parser = XMLReaderFactory.createXMLReader(
2989
"org.apache.crimson.parser.XMLReaderImpl"
2992
catch (SAXException ex) {
2993
// Can't test Crimson if you can't load it
2996
XMLFilter filter = new WarningFilter();
2997
filter.setParent(parser);
2998
Builder builder = new Builder(filter);
3000
Document doc = builder.build("<data/>", null);
3001
assertEquals("<?xml version=\"1.0\"?>\n<data />\n", doc.toXML());
3006
private static class WarningFilter extends XMLFilterImpl {
3008
public void startElement(String namespaceURI, String localName,
3009
String qualifiedName, Attributes atts) throws SAXException {
3011
this.getErrorHandler().warning(
3012
new SAXParseException("Warning", new LocatorImpl())
3014
super.startElement(namespaceURI, localName, qualifiedName,
3022
public void testSaxonsAElfredIsVerified()
3023
throws SAXException, IOException {
3027
parser = XMLReaderFactory.createXMLReader(
3028
"com.icl.saxon.aelfred.SAXDriver"
3031
catch (SAXException ex) {
3032
// Can't test SAXON if you can't load it
3035
Builder builder = new Builder(parser);
3038
// known bug in Saxon; doesn't catch
3039
// colon in processing instruction targets
3040
builder.build("<?test:data ?><data/>", null);
3041
fail("Didn't verify Saxon's input");
3043
catch (ParsingException success) {
3044
assertNotNull(success.getMessage());
3050
public void testSaxon7sAElfredIsVerified()
3051
throws SAXException, IOException {
3055
parser = XMLReaderFactory.createXMLReader(
3056
"net.sf.saxon.aelfred.SAXDriver"
3059
catch (SAXException ex) {
3060
// Can't test SAXON if you can't load it
3063
Builder builder = new Builder(parser);
3066
// known bug in Saxon: doesn't catch
3067
// colon in processing instruction targets
3068
builder.build("<?test:data ?><data/>", null);
3069
fail("Didn't verify Saxon's input");
3071
catch (ParsingException success) {
3072
assertNotNull(success.getMessage());
3078
public void testGNUJAXPIsVerified()
3079
throws SAXException, IOException {
3083
parser = XMLReaderFactory.createXMLReader(
3084
"gnu.xml.aelfred2.XmlReader"
3087
catch (SAXException ex) {
3088
// Can't test GNU JAXP if you can't load it
3091
Builder builder = new Builder(parser);
3094
// known bug in GNUJAXP: doesn't catch
3095
// colon in processing instruction targets
3096
builder.build("<?test:data ?><data/>", null);
3097
fail("Didn't verify GNU JAXP's input");
3099
catch (ParsingException success) {
3100
assertNotNull(success.getMessage());
3106
public void testCatalogOnTopOfTrustedParserIsTrusted() throws
3107
NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
3110
XMLReader parser = XMLReaderFactory.createXMLReader(
3111
"org.apache.crimson.parser.XMLReaderImpl"
3114
Class filter = Class.forName("org.apache.xml.resolver.tools.ResolvingXMLFilter");
3115
Class[] types = {XMLReader.class};
3116
Constructor constructor = filter.getConstructor(types);
3117
Object[] args = {parser};
3118
XMLReader reader = (XMLReader) constructor.newInstance(args);
3119
Builder builder = new Builder(reader);
3120
// If the factory is a nonverifying factory, then
3121
// getNodeFactory() won't return it.
3122
assertNull(builder.getNodeFactory());
3124
catch (ClassNotFoundException ex) {
3125
// Can't test if we can't find the class
3127
catch (SAXException ex) {
3128
// Need a trusted parser to test this
3134
// XML conformance test case xmlconf/xmltest/valid/not-sa/014.ent
3135
// shows how this can be necessary. In brief, the internal DTD
3136
// subset can define or override parameter entities used in the
3137
// external DTD subset, and that the external DTD subset depends
3138
// on for well-formedness
3139
public void testPreserveParameterEntitiesInInternalDTDSubset()
3140
throws ParsingException, IOException {
3142
String data = "<!DOCTYPE doc [\n"
3143
+ "<!ENTITY % e 'INCLUDE'>]><doc />";
3144
Document doc = builder.build(data, null);
3145
String subset = doc.getDocType().getInternalDTDSubset();
3146
assertEquals(" <!ENTITY % e \"INCLUDE\">\n", subset);
3151
public void testTrickyCaseFromAppendixA2OfXMLSpec()
3152
throws ParsingException, IOException {
3154
String data = "<?xml version='1.0'?>\n"
3155
+ "<!DOCTYPE test [\n"
3156
+ "<!ELEMENT test (#PCDATA) >\n"
3157
+ "<!ENTITY % xx '%zz;'>\n"
3158
+ "<!ENTITY % zz '<!ENTITY tricky \"error-prone\" >' >\n"
3161
+ "<test>This sample shows a &tricky; method.</test>\n";
3163
Document doc = builder.build(data, null);
3164
String s = doc.toXML();
3165
Document roundTrip = builder.build(s, null);
3166
assertEquals(doc, roundTrip);
3171
// This is an example of case where preserving external entity
3172
// declaration in internal DTD subset is necessary to maintain
3174
public void testPreserveExternalGeneralEntityDeclaration()
3175
throws ParsingException, IOException {
3177
Document doc = builder.build(new File(inputDir, "ge.xml"));
3178
DocType doctype = doc.getDocType();
3179
assertEquals(" <!ENTITY ccl SYSTEM \"ge.txt\">\n", doctype.getInternalDTDSubset());
3183
// This is an example of case where preserving external entity
3184
// declaration in internal DTD subset is necessary to maintain
3186
public void testPreserveExternalParameterEntityDeclaration()
3187
throws ParsingException, IOException {
3189
Document doc = builder.build(new File(inputDir, "pe.xml"));
3190
DocType doctype = doc.getDocType();
3191
assertEquals(" <!ENTITY % ccl SYSTEM \"pe.txt\">\n", doctype.getInternalDTDSubset());
3195
public void testNMTOKENSNormalizationOfCarriageReturnLineFeedEntityReferences()
3196
throws ParsingException, IOException {
3198
String data = "<!DOCTYPE attributes [\n"
3199
+ "<!ATTLIST attributes nmtokens NMTOKENS #IMPLIED>]>\n"
3200
+ "<attributes nmtokens = \" this
 also gets  normalized \" />";
3202
Document doc = builder.build(data, null);
3203
String s = doc.toXML();
3204
Document roundTrip = builder.build(s, null);
3205
assertEquals(doc, roundTrip);
3210
public void testXMLConformanceTestSuiteDocuments()
3211
throws ParsingException, IOException {
3213
File data = new File("data");
3214
File canonical = new File(data, "canonical");
3215
File masterList = new File(canonical, "xmlconf");
3216
masterList = new File(masterList, "xmlconf.xml");
3217
if (masterList.exists()) {
3218
Document xmlconf = builder.build(masterList);
3219
Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
3220
processTestCases(testcases);
3226
// xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
3228
private void processTestCases(Elements testcases)
3229
throws ParsingException, IOException {
3231
for (int i = 0; i < testcases.size(); i++) {
3232
Element testcase = testcases.get(i);
3233
Elements tests = testcase.getChildElements("TEST");
3234
processTests(tests);
3235
Elements level2 = testcase.getChildElements("TESTCASES");
3236
// need to be recursive to handle recursive IBM test cases
3237
processTestCases(level2);
3243
private void processTests(Elements tests)
3244
throws ParsingException, IOException {
3246
Element parent = new Element("e");
3247
Element child = new Element("a");
3248
parent.appendChild(child);
3250
int size = tests.size();
3251
for (int i = 0; i < size; i++) {
3252
Element test = tests.get(i);
3253
String namespace = test.getAttributeValue("NAMESPACE");
3254
if ("no".equals(namespace)) continue;
3255
String type = test.getAttributeValue("TYPE");
3256
if ("not-wf".equals(type)) continue;
3257
String uri = test.getAttributeValue("URI");
3258
String base = test.getBaseURI();
3259
// Hack because URIUtil isn't public; and I don't want to
3260
// depend on 1.4 only java.net.URI
3261
parent.setBaseURI(base);
3262
child.addAttribute(new Attribute("xml:base",
3263
"http://www.w3.org/XML/1998/namespace", uri));
3264
String resolvedURI = child.getBaseURI();
3266
Document doc = builder.build(resolvedURI);
3267
ByteArrayOutputStream out = new ByteArrayOutputStream();
3269
Serializer serializer = new Serializer(out);
3270
serializer.write(doc);
3275
byte[] actual = out.toByteArray();
3277
InputStream in = new ByteArrayInputStream(actual);
3279
Document roundTrip = builder.build(in, resolvedURI);
3280
assertEquals("Failed to roundtrip " + uri, doc, roundTrip);
3282
catch (ParsingException ex) {
3283
System.out.println(ex.getURI());
3284
System.out.println(doc.toXML());