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.BufferedInputStream;
25
import java.io.ByteArrayInputStream;
26
import java.io.ByteArrayOutputStream;
27
import java.io.DataInputStream;
29
import java.io.FileInputStream;
30
import java.io.FilenameFilter;
31
import java.io.IOException;
32
import java.io.InputStream;
33
import java.io.OutputStream;
35
import nu.xom.Attribute;
36
import nu.xom.Builder;
37
import nu.xom.Comment;
38
import nu.xom.DocType;
39
import nu.xom.Document;
40
import nu.xom.Element;
41
import nu.xom.Elements;
42
import nu.xom.Namespace;
44
import nu.xom.ParsingException;
45
import nu.xom.ProcessingInstruction;
46
import nu.xom.Serializer;
48
import nu.xom.XPathContext;
49
import nu.xom.canonical.CanonicalizationException;
50
import nu.xom.canonical.Canonicalizer;
54
* Tests canonicalization.
57
* @author Elliotte Rusty Harold
61
public class CanonicalizerTest extends XOMTestCase {
63
private final static double version = Double.parseDouble(
64
System.getProperty("java.version").substring(0,3)
67
private File canonical;
71
public CanonicalizerTest(String name) {
76
private Builder builder = new Builder();
79
protected void setUp() {
80
File data = new File("data");
81
canonical = new File(data, "canonical");
82
input = new File(canonical, "input");
83
output = new File(canonical, "output");
87
public void testCanonicalizeOnlyAttributes() throws IOException {
89
Element pdu = new Element("doc");
90
pdu.addAttribute(new Attribute("a1", "v1"));
91
pdu.addAttribute(new Attribute("a2", "v2"));
93
String expected = " a1=\"v1\" a2=\"v2\"";
94
ByteArrayOutputStream out = new ByteArrayOutputStream();
95
Canonicalizer canonicalizer = new Canonicalizer(out);
97
Document doc = new Document(pdu);
98
canonicalizer.write(doc.query("//@*"));
100
byte[] result = out.toByteArray();
102
String s = new String(out.toByteArray(), "UTF8");
103
assertEquals(expected, s);
108
public void testRemoveDuplicateAttributes() throws IOException {
110
Element pdu = new Element("doc");
111
Attribute a1 = new Attribute("a1", "v1");
112
pdu.addAttribute(a1);
113
Attribute a2 = new Attribute("a2", "v2");
114
pdu.addAttribute(a2);
116
String expected = " a1=\"v1\" a2=\"v2\"";
117
ByteArrayOutputStream out = new ByteArrayOutputStream();
118
Canonicalizer canonicalizer = new Canonicalizer(out);
120
Document doc = new Document(pdu);
121
Nodes subset = doc.query("//@*");
124
canonicalizer.write(subset);
126
byte[] result = out.toByteArray();
128
String s = new String(out.toByteArray(), "UTF8");
129
assertEquals(expected, s);
134
public void testCanonicalizeOnlyNamespaces() throws IOException {
136
Element pdu = new Element("doc", "http://www.example.com");
138
String expected = " xmlns=\"http://www.example.com\"";
139
ByteArrayOutputStream out = new ByteArrayOutputStream();
140
Canonicalizer canonicalizer = new Canonicalizer(out);
142
Document doc = new Document(pdu);
143
canonicalizer.write(doc.query("//namespace::node()"));
145
byte[] result = out.toByteArray();
147
String s = new String(out.toByteArray(), "UTF8");
148
assertEquals(expected, s);
153
public void testCanonicalizeOnlyPrefixedNamespaces()
156
Element pdu = new Element("pre:doc", "http://www.example.com");
158
String expected = " xmlns:pre=\"http://www.example.com\"";
159
ByteArrayOutputStream out = new ByteArrayOutputStream();
160
Canonicalizer canonicalizer = new Canonicalizer(out);
162
Document doc = new Document(pdu);
163
canonicalizer.write(doc.query("//namespace::node()"));
165
byte[] result = out.toByteArray();
167
String s = new String(out.toByteArray(), "UTF8");
168
assertEquals(expected, s);
173
public void testCanonicalizeWithNullAlgorithm()
176
ByteArrayOutputStream out = new ByteArrayOutputStream();
178
new Canonicalizer(out, null);
179
fail("Allowed null algorithm");
181
catch (NullPointerException success) {
182
assertNotNull(success.getMessage());
188
public void testCanonicalizeCommentsInPrologAndEpilog() throws IOException {
190
Element pdu = new Element("doc");
192
Document doc = new Document(pdu);
193
doc.insertChild(new Comment("comment 1"), 0);
194
doc.insertChild(new Comment("comment 2"), 1);
195
doc.appendChild(new Comment("comment 3"));
196
doc.appendChild(new Comment("comment 4"));
198
String expected = "<!--comment 1-->\n<!--comment 2-->\n\n<!--comment 3-->\n<!--comment 4-->";
199
ByteArrayOutputStream out = new ByteArrayOutputStream();
200
Canonicalizer canonicalizer = new Canonicalizer(out);
202
canonicalizer.write(doc.query("//comment()"));
204
byte[] result = out.toByteArray();
206
String s = new String(out.toByteArray(), "UTF8");
207
assertEquals(expected, s);
212
public void testTamin() throws ParsingException, IOException {
214
String input = "<ns1:root xmlns:ns1='http://www.example.org/'><elt1></elt1></ns1:root>";
215
Document doc = builder.build(input, null);
217
ByteArrayOutputStream out = new ByteArrayOutputStream();
218
Canonicalizer canonicalizer = new Canonicalizer(out);
220
canonicalizer.write(doc);
222
byte[] result = out.toByteArray();
224
String s = new String(out.toByteArray(), "UTF8");
225
assertEquals("<ns1:root xmlns:ns1=\"http://www.example.org/\"><elt1></elt1></ns1:root>", s);
230
public void testCanonicalizePrologAndEpilog() throws IOException {
232
Element pdu = new Element("doc");
234
Document doc = new Document(pdu);
235
doc.insertChild(new ProcessingInstruction("target", "value"), 0);
236
doc.insertChild(new Comment("comment 2"), 1);
237
doc.appendChild(new Comment("comment 3"));
238
doc.appendChild(new ProcessingInstruction("target", "value"));
240
String expected = "<?target value?>\n<!--comment 2-->\n<doc></doc>\n<!--comment 3-->\n<?target value?>";
241
ByteArrayOutputStream out = new ByteArrayOutputStream();
242
Canonicalizer canonicalizer = new Canonicalizer(out);
244
canonicalizer.write(doc);
246
byte[] result = out.toByteArray();
248
String s = new String(out.toByteArray(), "UTF8");
249
assertEquals(expected, s);
254
public void testCanonicalizeOnlyAttributesOnDifferentElements()
257
Element pdu = new Element("doc");
258
pdu.addAttribute(new Attribute("a2", "v1"));
259
Element child = new Element("child");
260
child.addAttribute(new Attribute("a1", "v2"));
261
pdu.appendChild(child);
263
String expected = " a2=\"v1\" a1=\"v2\"";
264
ByteArrayOutputStream out = new ByteArrayOutputStream();
265
Canonicalizer canonicalizer = new Canonicalizer(out);
267
Document doc = new Document(pdu);
268
canonicalizer.write(doc.query("//@*"));
270
byte[] result = out.toByteArray();
272
String s = new String(out.toByteArray(), "UTF8");
273
assertEquals(expected, s);
278
public void testCanonicalizeAttributesWithFunkyCharacters()
281
Element pdu = new Element("doc");
282
pdu.addAttribute(new Attribute("a2", "v1&<>\"\t\r\n"));
284
String expected = " a2=\"v1&<>"	
\"";
285
ByteArrayOutputStream out = new ByteArrayOutputStream();
286
Canonicalizer canonicalizer = new Canonicalizer(out);
288
Document doc = new Document(pdu);
289
canonicalizer.write(doc.query("//@*"));
291
byte[] result = out.toByteArray();
293
String s = new String(out.toByteArray(), "UTF8");
294
assertEquals(expected, s);
299
public void testExclusiveEmptyRootElementInNoNamespace()
302
Element pdu = new Element("doc");
304
String expected = "<doc></doc>";
305
ByteArrayOutputStream out = new ByteArrayOutputStream();
306
Canonicalizer canonicalizer = new Canonicalizer(out,
307
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
309
Document doc = new Document(pdu);
310
canonicalizer.write(doc);
312
byte[] result = out.toByteArray();
314
String s = new String(out.toByteArray(), "UTF8");
315
assertEquals(expected, s);
320
public void testExclusiveEmptyRootElementInNoNamespaceWithTwoAttributes()
323
Element pdu = new Element("doc");
324
pdu.addAttribute(new Attribute("a1", "v1"));
325
pdu.addAttribute(new Attribute("a2", "v2"));
327
String expected = "<doc a1=\"v1\" a2=\"v2\"></doc>";
328
ByteArrayOutputStream out = new ByteArrayOutputStream();
329
Canonicalizer canonicalizer = new Canonicalizer(out,
330
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
332
Document doc = new Document(pdu);
333
canonicalizer.write(doc);
335
byte[] result = out.toByteArray();
337
String s = new String(out.toByteArray(), "UTF8");
338
assertEquals(expected, s);
343
public void testExclusiveDoesntRenderUnusedPrefix()
346
Element pdu = new Element("n0:tuck", "http://a.example");
347
pdu.addNamespaceDeclaration("pre", "http://www.example.org/");
349
String expected = "<n0:tuck xmlns:n0=\"http://a.example\"></n0:tuck>";
350
ByteArrayOutputStream out = new ByteArrayOutputStream();
351
Canonicalizer canonicalizer = new Canonicalizer(out,
352
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
354
Document doc = new Document(pdu);
355
canonicalizer.write(doc);
357
byte[] result = out.toByteArray();
359
String s = new String(out.toByteArray(), "UTF8");
360
assertEquals(expected, s);
365
public void testWriteDefaultNamespace() throws IOException {
367
Element pdu = new Element("tuck", "http://www.example.org/");
369
String expected = " xmlns=\"http://www.example.org/\"";
370
ByteArrayOutputStream out = new ByteArrayOutputStream();
371
Canonicalizer canonicalizer = new Canonicalizer(out,
372
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
374
Document doc = new Document(pdu);
375
Nodes subset = doc.query("//namespace::node()");
376
canonicalizer.write(subset);
378
byte[] result = out.toByteArray();
380
String s = new String(out.toByteArray(), "UTF8");
381
assertEquals(expected, s);
386
public void testOutputAncestorAttributeAndChildHaveDifferentLanguages()
389
Element pdu = new Element("tuck");
390
pdu.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "fr"));
392
Element middle = new Element("middle");
393
pdu.appendChild(middle);
394
Element child = new Element("child");
395
child.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "en"));
396
middle.appendChild(child);
398
String expected = "<tuck xml:lang=\"fr\"><child xml:lang=\"en\"></child></tuck>";
399
ByteArrayOutputStream out = new ByteArrayOutputStream();
400
Canonicalizer canonicalizer = new Canonicalizer(out,
401
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
403
Document doc = new Document(pdu);
404
Nodes subset = doc.query("/* | //child | //@*");
405
canonicalizer.write(subset);
407
byte[] result = out.toByteArray();
409
String s = new String(out.toByteArray(), "UTF8");
410
assertEquals(expected, s);
415
public void testOutputAncestorAttributeUsesPrefix()
418
Element pdu = new Element("tuck");
419
pdu.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "value"));
420
Element child = new Element("pre:test", "http://www.example.org/");
421
pdu.appendChild(child);
423
String expected = "<tuck xmlns:pre=\"http://www.example.org/\" pre:foo=\"value\"><pre:test></pre:test></tuck>";
424
ByteArrayOutputStream out = new ByteArrayOutputStream();
425
Canonicalizer canonicalizer = new Canonicalizer(out,
426
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
428
Document doc = new Document(pdu);
429
canonicalizer.write(doc);
431
byte[] result = out.toByteArray();
433
String s = new String(out.toByteArray(), "UTF8");
434
assertEquals(expected, s);
439
public void testOutputAncestorAttributeRedefinesPrefix()
442
Element pdu = new Element("tuck");
443
pdu.addAttribute(new Attribute("pre:foo", "http://www.example.com/", "value"));
444
Element child = new Element("pre:test", "http://www.example.org/");
445
pdu.appendChild(child);
447
String expected = "<tuck xmlns:pre=\"http://www.example.com/\" "
448
+ "pre:foo=\"value\"><pre:test xmlns:pre=\"http://www.example.org/\"></pre:test></tuck>";
449
ByteArrayOutputStream out = new ByteArrayOutputStream();
450
Canonicalizer canonicalizer = new Canonicalizer(out,
451
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
453
Document doc = new Document(pdu);
454
canonicalizer.write(doc);
456
byte[] result = out.toByteArray();
458
String s = new String(out.toByteArray(), "UTF8");
459
assertEquals(expected, s);
464
public void testExclusiveDoesntRenderUnusedPrefixFromUnincludedAttribute()
467
Element pdu = new Element("n0:tuck", "http://a.example");
468
pdu.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "test"));
470
String expected = "<n0:tuck xmlns:n0=\"http://a.example\"></n0:tuck>";
471
ByteArrayOutputStream out = new ByteArrayOutputStream();
472
Canonicalizer canonicalizer = new Canonicalizer(out,
473
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
475
Document doc = new Document(pdu);
476
canonicalizer.write(doc.query("//* | //namespace::node()"));
478
byte[] result = out.toByteArray();
480
String s = new String(out.toByteArray(), "UTF8");
481
assertEquals(expected, s);
486
public void testWithComments()
487
throws ParsingException, IOException {
490
String[] inputs = tests.list(new XMLFilter());
491
for (int i = 0; i < inputs.length; i++) {
492
File input = new File(tests, inputs[i]);
493
Document doc = builder.build(input);
494
ByteArrayOutputStream out = new ByteArrayOutputStream();
496
Canonicalizer serializer = new Canonicalizer(out);
497
serializer.write(doc);
502
byte[] actual = out.toByteArray();
505
/* File debug = new File(canonical, "debug/"
506
+ input.getName() + ".dbg");
507
OutputStream fout = new FileOutputStream(debug);
511
File expected = new File(output, input.getName() + ".out");
513
input.getName(), expected.length(), actual.length);
514
byte[] expectedBytes = new byte[actual.length];
515
InputStream fin = new FileInputStream(expected);
516
DataInputStream in = new DataInputStream(fin);
518
in.readFully(expectedBytes);
523
for (int j = 0; j < expectedBytes.length; j++) {
524
assertEquals(expectedBytes[i], actual[i]);
532
public void testNamedAlgorithmWithComments()
533
throws ParsingException, IOException {
536
String[] inputs = tests.list(new XMLFilter());
537
for (int i = 0; i < inputs.length; i++) {
538
File input = new File(tests, inputs[i]);
539
Document doc = builder.build(input);
540
ByteArrayOutputStream out = new ByteArrayOutputStream();
542
Canonicalizer serializer = new Canonicalizer(
543
out, Canonicalizer.CANONICAL_XML_WITH_COMMENTS);
544
serializer.write(doc);
549
byte[] actual = out.toByteArray();
552
/* File debug = new File(canonical, "debug/"
553
+ input.getName() + ".dbg");
554
OutputStream fout = new FileOutputStream(debug);
558
File expected = new File(output, input.getName() + ".out");
560
input.getName(), expected.length(), actual.length);
561
byte[] expectedBytes = new byte[actual.length];
562
InputStream fin = new FileInputStream(expected);
563
DataInputStream in = new DataInputStream(fin);
565
in.readFully(expectedBytes);
570
for (int j = 0; j < expectedBytes.length; j++) {
571
assertEquals(expectedBytes[i], actual[i]);
579
public void testWithoutComments()
580
throws ParsingException, IOException {
583
String[] inputs = tests.list(new XMLFilter());
584
for (int i = 0; i < inputs.length; i++) {
585
File input = new File(tests, inputs[i]);
586
Document doc = builder.build(input);
588
ByteArrayOutputStream out = new ByteArrayOutputStream();
590
Canonicalizer serializer
591
= new Canonicalizer(out, false);
592
serializer.write(doc);
598
byte[] actual = out.toByteArray();
600
File expected = new File(canonical, "wocommentsoutput/");
601
expected = new File(expected, input.getName() + ".out");
602
byte[] expectedBytes = new byte[actual.length];
603
InputStream fin = new FileInputStream(expected);
604
DataInputStream in = new DataInputStream(fin);
606
in.readFully(expectedBytes);
611
for (int j = 0; j < expectedBytes.length; j++) {
612
assertEquals(expectedBytes[i], actual[i]);
621
public void testNamedAlgorithmWithoutComments()
622
throws ParsingException, IOException {
625
String[] inputs = tests.list(new XMLFilter());
626
for (int i = 0; i < inputs.length; i++) {
627
File input = new File(tests, inputs[i]);
628
Document doc = builder.build(input);
630
ByteArrayOutputStream out = new ByteArrayOutputStream();
632
Canonicalizer serializer = new Canonicalizer(
633
out, Canonicalizer.CANONICAL_XML);
634
serializer.write(doc);
640
byte[] actual = out.toByteArray();
642
File expected = new File(canonical, "wocommentsoutput/");
643
expected = new File(expected, input.getName() + ".out");
644
byte[] expectedBytes = new byte[actual.length];
645
InputStream fin = new FileInputStream(expected);
646
DataInputStream in = new DataInputStream(fin);
648
in.readFully(expectedBytes);
653
for (int j = 0; j < expectedBytes.length; j++) {
654
assertEquals(expectedBytes[i], actual[i]);
663
public void testXMLNamespaceAttributeInheritance()
666
Element root = new Element("root");
667
Document doc = new Document(root);
668
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
669
root.appendChild(new Element("child312"));
671
String expected = "<child312 xml:id=\"p1\"></child312>";
673
ByteArrayOutputStream out = new ByteArrayOutputStream();
675
Canonicalizer serializer = new Canonicalizer(out, false);
676
serializer.write(doc.query("/*/child312"));
682
String actual = new String(out.toByteArray(), "UTF-8");
683
assertEquals(expected, actual);
688
public void testXMLNamespaceAttributeInheritanceThroughMultipleLevels()
691
Element superroot = new Element("superroot");
692
Element root = new Element("root");
693
superroot.appendChild(root);
694
superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
695
Document doc = new Document(superroot);
696
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
697
root.appendChild(new Element("child312"));
699
String expected = "<child312 xml:id=\"p1\"></child312>";
701
ByteArrayOutputStream out = new ByteArrayOutputStream();
703
Canonicalizer serializer = new Canonicalizer(out, false);
704
Nodes result = doc.query("/*/*/child312");
705
serializer.write(result);
711
String actual = new String(out.toByteArray(), "UTF-8");
712
assertEquals(expected, actual);
717
public void testXMLNamespaceAttributeInheritanceThroughMultipleLevelsWithSkippedMiddle()
720
Element superroot = new Element("superroot");
721
Element root = new Element("root");
722
superroot.appendChild(root);
723
superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
724
Document doc = new Document(superroot);
725
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
726
root.appendChild(new Element("child312"));
728
String expected = "<superroot xml:id=\"p0\"><child312 xml:id=\"p1\"></child312></superroot>";
730
ByteArrayOutputStream out = new ByteArrayOutputStream();
732
Canonicalizer serializer = new Canonicalizer(out, false);
733
serializer.write(doc.query("/* | //child312 | /*/@* | //child312/@*"));
739
String actual = new String(out.toByteArray(), "UTF-8");
740
assertEquals(expected, actual);
745
public void testXMLNamespaceAttributeInheritanceNearestIsInSubset()
748
Element superroot = new Element("superroot");
749
Element root = new Element("root");
750
superroot.appendChild(root);
751
superroot.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p0"));
752
Document doc = new Document(superroot);
753
root.appendChild(new Element("child312"));
755
String expected = "<superroot xml:id=\"p0\"><child312></child312></superroot>";
757
ByteArrayOutputStream out = new ByteArrayOutputStream();
759
Canonicalizer serializer = new Canonicalizer(out, false);
760
serializer.write(doc.query("/* | //child312 | /*/@* | //child312/@*"));
766
String actual = new String(out.toByteArray(), "UTF-8");
767
assertEquals(expected, actual);
772
public void testXMLNamespaceAttributeNotOverridden()
775
Element root = new Element("root");
776
Document doc = new Document(root);
777
Element child = new Element("child312");
779
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
780
child.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p2"));
782
root.appendChild(child);
784
String expected = "<child312 xml:id=\"p2\"></child312>";
786
ByteArrayOutputStream out = new ByteArrayOutputStream();
788
Canonicalizer serializer = new Canonicalizer(out, false);
789
serializer.write(doc.query("/*/child312 | /*/*/@*"));
795
String actual = new String(out.toByteArray(), "UTF-8");
796
assertEquals(expected, actual);
801
public void testXMLNamespaceAttributeNotOverridden2()
804
Element root = new Element("root");
805
Document doc = new Document(root);
806
Element child = new Element("child312");
808
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
809
child.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p2"));
811
root.appendChild(child);
813
String expected = "<child312></child312>";
815
ByteArrayOutputStream out = new ByteArrayOutputStream();
817
Canonicalizer serializer = new Canonicalizer(out, false);
818
serializer.write(doc.query("/*/child312 "));
824
String actual = new String(out.toByteArray(), "UTF-8");
825
assertEquals(expected, actual);
830
public void testXMLNamespaceAttributeNotInheritedWithExclusiveCanonicalization()
833
Element root = new Element("root");
834
Document doc = new Document(root);
835
root.addAttribute(new Attribute("xml:id", Namespace.XML_NAMESPACE, "p1"));
836
root.appendChild(new Element("child312"));
838
String expected = "<child312></child312>";
840
ByteArrayOutputStream out = new ByteArrayOutputStream();
842
Canonicalizer serializer = new Canonicalizer(out,
843
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
844
serializer.write(doc.query("/*/child312"));
850
String actual = new String(out.toByteArray(), "UTF-8");
851
assertEquals(expected, actual);
856
public void testXMLNSAttributeNotInheritedWithExclusiveCanonicalization()
859
Element root = new Element("root", "http://www.example.org/");
860
Document doc = new Document(root);
861
root.appendChild(new Element("child312", "http://www.example.org/"));
863
String expected = "<child312 xmlns=\"http://www.example.org/\"></child312>";
865
ByteArrayOutputStream out = new ByteArrayOutputStream();
867
Canonicalizer serializer = new Canonicalizer(out,
868
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
869
XPathContext context = new XPathContext("pre", "http://www.example.org/");
870
serializer.write(doc.query("/*/pre:child312 | /*/pre:child312/namespace::node()",
877
String actual = new String(out.toByteArray(), "UTF-8");
878
assertEquals(expected, actual);
883
public void testXMLNSPrefixAttributeInheritedWithExclusiveCanonicalization()
886
Element root = new Element("pre:root", "http://www.example.org/");
887
Document doc = new Document(root);
888
root.appendChild(new Element("pre:child312", "http://www.example.org/"));
890
String expected = "<pre:child312 xmlns:pre=\"http://www.example.org/\"></pre:child312>";
892
ByteArrayOutputStream out = new ByteArrayOutputStream();
894
XPathContext context = new XPathContext("pre", "http://www.example.org/");
895
Canonicalizer serializer = new Canonicalizer(out,
896
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
897
serializer.write(doc.query("/*/pre:child312 | /*/pre:child312/namespace::node()", context));
903
String actual = new String(out.toByteArray(), "UTF-8");
904
assertEquals(expected, actual);
909
public void testXMLNSEqualsEmptyString()
912
Element root = new Element("root", "http://www.ietf.org");
913
Document doc = new Document(root);
914
root.appendChild(new Element("child"));
916
String expected = "<root xmlns=\"http://www.ietf.org\"><child xmlns=\"\"></child></root>";
918
ByteArrayOutputStream out = new ByteArrayOutputStream();
920
Canonicalizer serializer = new Canonicalizer(out, false);
921
serializer.write(doc);
927
String actual = new String(out.toByteArray(), "UTF-8");
928
assertEquals(expected, actual);
933
// from section 3.7 of spec
934
public void testDocumentSubsetCanonicalization()
935
throws ParsingException, IOException {
937
String input = "<!DOCTYPE doc [\n"
938
+ "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
939
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
941
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
943
+ " <e2 xmlns=\"\">\n"
944
+ " <e3 id=\"E3\"/>\n"
949
Document doc = builder.build(input, null);
950
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
951
String xpath = "(//. | //@* | //namespace::*)\n"
953
+ "self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2))"
955
+ " count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n"
958
String expected = "<e1 xmlns=\"http://www.ietf.org\" "
959
+ "xmlns:w3c=\"http://www.w3.org\"><e3 xmlns=\"\" id=\"E3\" xml:space=\"preserve\"></e3></e1>";
961
ByteArrayOutputStream out = new ByteArrayOutputStream();
963
Canonicalizer serializer = new Canonicalizer(out, false);
964
serializer.write(doc.query(xpath, context));
970
String actual = new String(out.toByteArray(), "UTF-8");
971
assertEquals(expected, actual);
976
public void testCanonicalizeEmptyDocumentSubset()
977
throws ParsingException, IOException {
979
String input = "<!DOCTYPE doc [\n"
980
+ "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
981
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
983
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
985
+ " <e2 xmlns=\"\">\n"
986
+ " <e3 id=\"E3\"/>\n"
991
Document doc = builder.build(input, null);
992
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
993
String xpath = "//aaa";
994
ByteArrayOutputStream out = new ByteArrayOutputStream();
996
Canonicalizer serializer = new Canonicalizer(out, false);
997
serializer.write(doc.query(xpath, context));
1003
String actual = new String(out.toByteArray(), "UTF-8");
1004
assertEquals("", actual);
1009
public void testDocumentSubsetCanonicalizationSkippingProcessingInstructions()
1010
throws ParsingException, IOException {
1012
String input = "<!DOCTYPE doc [\n"
1013
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
1015
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
1017
+ " <e2 xmlns=\"\">\n"
1018
+ " <e3 id=\"E3\"/>\n"
1023
String expected = "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
1025
+ " <e2 xmlns=\"\">\n"
1026
+ " <e3 id=\"E3\"></e3>\n"
1031
Document doc = builder.build(input, null);
1032
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
1033
String xpath = "//* | //text() | //@* | //namespace::*";
1035
ByteArrayOutputStream out = new ByteArrayOutputStream();
1037
Canonicalizer serializer = new Canonicalizer(out, false);
1038
serializer.write(doc.query(xpath, context));
1044
String actual = new String(out.toByteArray(), "UTF-8");
1045
assertEquals(expected, actual);
1050
public void testDocumentSubsetCanonicalizationWithoutSelectingPrologAndEpilog()
1051
throws ParsingException, IOException {
1053
String input = "<!-- prolog -->\n"
1054
+ "<!DOCTYPE doc [\n"
1055
+ "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
1056
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
1058
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
1060
+ " <e2 xmlns=\"\">\n"
1061
+ " <e3 id=\"E3\"/>\n"
1064
+ "</doc><!-- epilog -->";
1066
Document doc = builder.build(input, null);
1067
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
1068
String xpath = "(/*//. | //@* | //namespace::*)\n"
1070
+ "self::ietf:e1 or (parent::ietf:e1 and not(self::text() or self::e2))"
1072
+ " count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n"
1075
String expected = "<e1 xmlns=\"http://www.ietf.org\" "
1076
+ "xmlns:w3c=\"http://www.w3.org\"><e3 xmlns=\"\" id=\"E3\" xml:space=\"preserve\"></e3></e1>";
1078
ByteArrayOutputStream out = new ByteArrayOutputStream();
1080
Canonicalizer serializer = new Canonicalizer(out, Canonicalizer.CANONICAL_XML_WITH_COMMENTS);
1081
serializer.write(doc.query(xpath, context));
1087
String actual = new String(out.toByteArray(), "UTF-8");
1088
assertEquals(expected, actual);
1093
public void testEmptyDefaultNamespace()
1094
throws ParsingException, IOException {
1096
String input = "<doc xmlns=\"http://www.ietf.org\">"
1097
+ "<e2 xmlns=\"\"></e2>"
1100
Document doc = builder.build(input, null);
1101
String xpath = "(//* | //namespace::*)";
1103
String expected = input;
1105
ByteArrayOutputStream out = new ByteArrayOutputStream();
1107
Canonicalizer serializer = new Canonicalizer(out, false);
1108
serializer.write(doc.query(xpath));
1114
String actual = new String(out.toByteArray(), "UTF-8");
1115
assertEquals(expected, actual);
1121
public void testDocumentSubsetCanonicalizationSimple()
1122
throws ParsingException, IOException {
1124
String input = "<!DOCTYPE doc [\n"
1125
+ "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
1126
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
1128
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
1130
+ " <e2 xmlns=\"\">\n"
1131
+ " <e3 id=\"E3\"/>\n"
1136
Document doc = builder.build(input, null);
1137
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
1138
String xpath = "(/* | /*/namespace::*)\n";
1140
String expected = "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\"></doc>";
1142
ByteArrayOutputStream out = new ByteArrayOutputStream();
1144
Canonicalizer serializer = new Canonicalizer(out, false);
1145
serializer.write(doc.query(xpath, context));
1151
String actual = new String(out.toByteArray(), "UTF-8");
1152
assertEquals(expected, actual);
1157
public void testCanonicalizeDocumentSubsetIncludingRoot()
1158
throws ParsingException, IOException {
1160
String input = "<doc />";
1162
Document doc = builder.build(input, null);
1164
String expected = "<doc></doc>";
1166
ByteArrayOutputStream out = new ByteArrayOutputStream();
1168
Canonicalizer serializer = new Canonicalizer(out, false);
1169
Nodes subset = doc.query("//.");
1170
serializer.write(subset);
1176
String actual = new String(out.toByteArray(), "UTF-8");
1177
assertEquals(expected, actual);
1182
public void testCanonicalizeDocumentSubsetThatOnlyContainsRoot()
1183
throws IOException {
1185
Document doc = new Document(new Element("root"));
1187
ByteArrayOutputStream out = new ByteArrayOutputStream();
1189
Canonicalizer serializer = new Canonicalizer(out, false);
1190
Nodes subset = doc.query("/");
1191
serializer.write(subset);
1197
String actual = new String(out.toByteArray(), "UTF-8");
1198
assertEquals("", actual);
1203
public void testDocumentSubsetCanonicalizationNamespaceInheritance()
1204
throws ParsingException, IOException {
1206
String input = "<!DOCTYPE doc [\n"
1207
+ "<!ATTLIST e2 xml:space (default|preserve) 'preserve'>\n"
1208
+ "<!ATTLIST e3 id ID #IMPLIED>\n"
1210
+ "<doc xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\">\n"
1212
+ " <e2 xmlns=\"\">\n"
1213
+ " <e3 id=\"E3\"/>\n"
1218
Document doc = builder.build(input, null);
1219
XPathContext context = new XPathContext("ietf", "http://www.ietf.org");
1220
String xpath = "(/*/* | /*/*/namespace::*)\n";
1222
String expected = "<e1 xmlns=\"http://www.ietf.org\" xmlns:w3c=\"http://www.w3.org\"></e1>";
1224
ByteArrayOutputStream out = new ByteArrayOutputStream();
1226
Canonicalizer serializer = new Canonicalizer(out, false);
1227
serializer.write(doc.query(xpath, context));
1233
String actual = new String(out.toByteArray(), "UTF-8");
1234
assertEquals(expected, actual);
1239
public void testRelativeNamespaceURIsForbidden()
1240
throws ParsingException, IOException {
1243
String data = "<test xmlns=\"relative\">data</test>";
1244
Document doc = builder.build(data, "http://www.ex.org/");
1245
ByteArrayOutputStream out = new ByteArrayOutputStream();
1246
Canonicalizer serializer
1247
= new Canonicalizer(out, false);
1248
serializer.write(doc);
1249
fail("Canonicalized document with relative namespace URI");
1251
catch (ParsingException success) {
1252
assertNotNull(success.getMessage());
1258
private static class XMLFilter implements FilenameFilter {
1260
public boolean accept(File directory, String name) {
1261
if (name.endsWith(".xml")) return true;
1268
public void testNFCFromISO88591()
1269
throws ParsingException, IOException {
1270
isoNormalizationTest("ISO-8859-1");
1274
public void testNFCFromISO88592()
1275
throws ParsingException, IOException {
1276
isoNormalizationTest("ISO-8859-2");
1280
public void testNFCFromISO88593()
1281
throws ParsingException, IOException {
1282
isoNormalizationTest("ISO-8859-3");
1286
public void testNFCFromISO88594()
1287
throws ParsingException, IOException {
1288
isoNormalizationTest("ISO-8859-4");
1292
public void testNFCFromISO88595()
1293
throws ParsingException, IOException {
1294
isoNormalizationTest("ISO-8859-5");
1298
public void testNFCFromISO88596()
1299
throws ParsingException, IOException {
1301
// This test fails in 1.2.2 due to an apparent bug in the
1302
// conversion of the characters '1' and '0' to bytes in
1304
isoNormalizationTest("ISO-8859-6");
1309
public void testNFCFromISO88597()
1310
throws ParsingException, IOException {
1311
isoNormalizationTest("ISO-8859-7");
1315
public void testNFCFromISO88598()
1316
throws ParsingException, IOException {
1317
isoNormalizationTest("ISO-8859-8");
1321
public void testNFCFromISO88599()
1322
throws ParsingException, IOException {
1323
isoNormalizationTest("ISO-8859-9");
1327
public void testNFCFromISO885913()
1328
throws ParsingException, IOException {
1330
if (version >= 1.3) {
1331
// iSO-8859-6 not supported in Java 1.2
1332
isoNormalizationTest("ISO-8859-13");
1338
public void testNFCFromISO885915()
1339
throws ParsingException, IOException {
1340
isoNormalizationTest("ISO-8859-15");
1344
// 14 and 16 aren't tested because Java doesn't support them yet
1345
private void isoNormalizationTest(String encoding)
1346
throws ParsingException, IOException {
1348
String prolog = "<?xml version='1.0' encoding='"
1349
+ encoding + "'?>\r\n<root>";
1351
byte[] prologData = prolog.getBytes(encoding);
1353
String epilog = "</root>";
1354
byte[] epilogData = epilog.getBytes(encoding);
1355
byte[] data = new byte[prologData.length + epilogData.length + 255 - 160 + 1];
1356
System.arraycopy(prologData, 0, data, 0, prologData.length);
1357
System.arraycopy(epilogData, 0, data,
1358
data.length - epilogData.length, epilogData.length);
1359
for (int i = 160; i <= 255; i++) {
1360
data[prologData.length + (i-160)] = (byte) i;
1362
InputStream in = new ByteArrayInputStream(data);
1363
Document doc = builder.build(in);
1365
// make a Unicode normalized version of the same document
1366
ByteArrayOutputStream out = new ByteArrayOutputStream();
1367
Serializer serializer = new Serializer(out);
1368
serializer.setUnicodeNormalizationFormC(true);
1369
serializer.write(doc);
1370
byte[] temp = out.toByteArray();
1371
in = new ByteArrayInputStream(temp);
1372
Document nfcDoc = builder.build(in);
1374
assertEquals("Parser doesn't use NFC when converting from " + encoding,
1380
public void testEBCDIC()
1381
throws ParsingException, IOException {
1383
String encoding = "IBM037";
1384
String prolog = "<?xml version='1.0' encoding='"
1385
+ encoding + "'?>\r\n<root>";
1386
byte[] prologData = prolog.getBytes(encoding);
1387
String epilog = "</root>";
1388
byte[] epilogData = epilog.getBytes(encoding);
1389
byte[] data = new byte[prologData.length + epilogData.length + 255 - 160 + 1];
1390
System.arraycopy(prologData, 0, data, 0, prologData.length);
1391
System.arraycopy(epilogData, 0, data,
1392
data.length - epilogData.length, epilogData.length);
1393
StringBuffer buffer = new StringBuffer(255 - 160 + 1);
1394
for (int i = 160; i <= 255; i++) {
1395
buffer.append((char) i);
1397
byte[] temp = buffer.toString().getBytes(encoding);
1398
System.arraycopy(temp, 0, data, prologData.length, temp.length);
1399
InputStream in = new ByteArrayInputStream(data);
1400
Document doc = builder.build(in);
1402
// make a Unicode normalized version of the same document
1403
ByteArrayOutputStream out = new ByteArrayOutputStream();
1404
Serializer serializer = new Serializer(out);
1405
serializer.setUnicodeNormalizationFormC(true);
1406
serializer.write(doc);
1407
temp = out.toByteArray();
1408
in = new ByteArrayInputStream(temp);
1409
Document nfcDoc = builder.build(in);
1411
// String normalizedResult = Normalizer.normalize(rawResult, Normalizer.NFC);
1412
assertEquals("Parser doesn't use NFC when converting from " + encoding,
1418
// make sure null pointer exception doesn't cause any output
1419
public void testNullDocument()
1420
throws IOException {
1422
ByteArrayOutputStream out = new ByteArrayOutputStream();
1423
Canonicalizer canonicalizer = new Canonicalizer(out);
1425
canonicalizer.write((Document) null);
1426
fail("Wrote null document");
1428
catch (NullPointerException success) {
1431
byte[] result = out.toByteArray();
1432
assertEquals(0, result.length);
1437
public void testWhiteSpaceTrimmingInNonCDATAAttribute()
1438
throws IOException {
1440
Attribute attribute = new Attribute("name", " value1 value2 ");
1441
attribute.setType(Attribute.Type.NMTOKENS);
1442
Element root = new Element("root");
1443
root.addAttribute(attribute);
1444
Document doc = new Document(root);
1445
ByteArrayOutputStream out = new ByteArrayOutputStream();
1446
Canonicalizer canonicalizer = new Canonicalizer(out);
1447
canonicalizer.write(doc);
1449
String result = new String(out.toByteArray(), "UTF8");
1450
assertEquals("<root name=\"value1 value2\"></root>", result);
1455
// compare to output generated by Apache XML Security code
1456
public void testXMLConformanceTestSuiteDocuments()
1457
throws ParsingException, IOException {
1459
File masterList = new File(canonical, "xmlconf");
1460
masterList = new File(masterList, "xmlconf.xml");
1461
if (masterList.exists()) {
1462
Document xmlconf = builder.build(masterList);
1463
Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
1464
processTestCases(testcases);
1470
// xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
1472
private void processTestCases(Elements testcases)
1473
throws ParsingException, IOException {
1475
for (int i = 0; i < testcases.size(); i++) {
1476
Element testcase = testcases.get(i);
1477
Elements tests = testcase.getChildElements("TEST");
1478
processTests(tests);
1479
Elements level2 = testcase.getChildElements("TESTCASES");
1480
// need to be recursive to handle recursive IBM test cases
1481
processTestCases(level2);
1487
private void processTests(Elements tests)
1488
throws ParsingException, IOException {
1490
Element parent = new Element("e");
1491
Element child = new Element("a");
1492
parent.appendChild(child);
1494
int size = tests.size();
1495
for (int i = 0; i < size; i++) {
1496
Element test = tests.get(i);
1497
String namespace = test.getAttributeValue("NAMESPACE");
1498
if ("no".equals(namespace)) continue;
1499
String type = test.getAttributeValue("TYPE");
1500
if ("not-wf".equals(type)) continue;
1501
String uri = test.getAttributeValue("URI");
1502
String base = test.getBaseURI();
1503
// Hack because URIUtil isn't public; and I don't want to
1504
// depend on 1.4 only java.net.URI
1505
parent.setBaseURI(base);
1507
child.addAttribute(new Attribute("xml:base",
1508
"http://www.w3.org/XML/1998/namespace", uri));
1509
String resolvedURI = child.getBaseURI();
1511
Document doc = builder.build(resolvedURI);
1512
ByteArrayOutputStream out = new ByteArrayOutputStream();
1514
Canonicalizer serializer = new Canonicalizer(out);
1515
serializer.write(doc);
1520
byte[] actual = out.toByteArray();
1522
File input = new File(resolvedURI.substring(5) + ".can");
1523
assertEquals(resolvedURI, input.length(), actual.length);
1524
byte[] expected = new byte[actual.length];
1525
DataInputStream in = new DataInputStream(
1526
new BufferedInputStream(new FileInputStream(input)));
1528
in.readFully(expected);
1533
assertEquals(expected, actual);
1540
public void testExclusive() throws IOException {
1542
Element pdu = new Element("n0:pdu", "http://a.example");
1543
Element elem1 = new Element("n1:elem1", "http://b.example");
1544
elem1.appendChild("content");
1545
pdu.appendChild(elem1);
1547
String expected = "<n1:elem1 xmlns:n1=\"http://b.example\">content</n1:elem1>";
1548
ByteArrayOutputStream out = new ByteArrayOutputStream();
1549
Canonicalizer canonicalizer = new Canonicalizer(out,
1550
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1552
XPathContext context = new XPathContext("n1", "http://b.example");
1553
Document doc = new Document(pdu);
1554
canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]", context));
1556
byte[] result = out.toByteArray();
1558
String s = new String(out.toByteArray(), "UTF8");
1559
assertEquals(expected, s);
1563
public static void testAustB() throws IOException {
1565
Element e1 = new Element("a:a", "urn:a");
1566
Element e2 = new Element("b");
1569
ByteArrayOutputStream out = new ByteArrayOutputStream();
1570
Canonicalizer c = new Canonicalizer(out,
1571
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
1573
String s = out.toString("UTF8");
1574
assertEquals("<a:a xmlns:a=\"urn:a\"><b></b></a:a>", s);
1579
public static void testAustB2() throws IOException {
1581
Element e1 = new Element("a:a", "urn:a");
1582
Element e2 = new Element("b");
1585
ByteArrayOutputStream out = new ByteArrayOutputStream();
1586
Canonicalizer c = new Canonicalizer(out);
1588
String s = out.toString("UTF8");
1589
assertEquals("<a:a xmlns:a=\"urn:a\"><b></b></a:a>", s);
1594
public static void testAust() throws Exception {
1596
Element e1 = new Element("a:a", "urn:a");
1597
Element e2 = new Element("a:b", "urn:a");
1599
ByteArrayOutputStream out = new ByteArrayOutputStream();
1600
Canonicalizer c = new Canonicalizer(out,
1601
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
1603
String s = out.toString("UTF8");
1604
assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
1609
public static void testAust4() throws Exception {
1611
Element e1 = new Element("a:a", "urn:a");
1612
Element e2 = new Element("a:b", "urn:a");
1614
ByteArrayOutputStream out = new ByteArrayOutputStream();
1615
Canonicalizer canonicalizer = new Canonicalizer(out,
1616
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1617
XPathContext context = new XPathContext("a", "urn:a");
1618
Document doc = new Document(e1);
1619
canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::a:b]", context));
1621
String s = out.toString("UTF8");
1622
assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
1627
public static void testAust5() throws Exception {
1629
Element e1 = new Element("a:a", "urn:a");
1630
Element e2 = new Element("a:b", "urn:a");
1632
ByteArrayOutputStream out = new ByteArrayOutputStream();
1633
Canonicalizer canonicalizer = new Canonicalizer(out,
1634
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1635
Document doc = new Document(e1);
1636
Nodes set = new Nodes(e2);
1637
canonicalizer.write(set);
1639
String s = out.toString("UTF8");
1640
// The namespace was not explicitly included in
1641
// the set so it should not be output.
1642
assertEquals("<a:b></a:b>", s);
1647
public static void testAust3() throws Exception {
1649
Element e2 = new Element("a:b", "urn:a");
1650
ByteArrayOutputStream os = new ByteArrayOutputStream();
1651
new Canonicalizer(os,
1652
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION).write(e2);
1653
String s = os.toString("UTF8");
1654
assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
1659
public static void testAust2() throws Exception {
1661
Element e1 = new Element("a:a", "urn:a");
1662
Element e2 = new Element("a:b", "urn:a");
1664
ByteArrayOutputStream os = new ByteArrayOutputStream();
1665
new Canonicalizer(os,
1666
Canonicalizer.CANONICAL_XML).write(e2);
1667
String s = os.toString("UTF8");
1668
assertEquals("<a:b xmlns:a=\"urn:a\"></a:b>", s);
1673
public void testExclusiveWithNamespacedAttributes() throws IOException {
1675
Element pdu = new Element("n0:pdu", "http://a.example");
1676
Element elem1 = new Element("n1:elem1", "http://b.example");
1677
elem1.appendChild("content");
1678
pdu.appendChild(elem1);
1679
elem1.addAttribute(new Attribute("pre:foo", "http://www.example.org/", "value"));
1681
String expected = "<n1:elem1 xmlns:n1=\"http://b.example\" "
1682
+ "xmlns:pre=\"http://www.example.org/\" pre:foo=\"value\">content</n1:elem1>";
1683
ByteArrayOutputStream out = new ByteArrayOutputStream();
1684
Canonicalizer canonicalizer = new Canonicalizer(out,
1685
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1687
XPathContext context = new XPathContext("n1", "http://b.example");
1688
Document doc = new Document(pdu);
1689
canonicalizer.write(doc.query("(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]", context));
1691
byte[] result = out.toByteArray();
1693
String s = new String(out.toByteArray(), "UTF8");
1694
assertEquals(expected, s);
1699
/* <root xml:lang="en"><a><b>test</b></a></root>
1701
Choose the document subset selected by /root//node()
1705
<a xml:lang="en"><b>test</b></a> */
1706
public void testInheritanceOfXMLLang() throws IOException {
1708
Element root = new Element("root");
1709
root.addAttribute(new Attribute("xml:lang", Namespace.XML_NAMESPACE, "en"));
1710
Element a = new Element("a");
1711
Element b = new Element("b");
1712
b.appendChild("test");
1714
root.appendChild(a);
1716
String expected = "<a xml:lang=\"en\"><b>test</b></a>";
1717
ByteArrayOutputStream out = new ByteArrayOutputStream();
1718
Canonicalizer canonicalizer = new Canonicalizer(out, Canonicalizer.CANONICAL_XML);
1720
Document doc = new Document(root);
1721
canonicalizer.write(doc.query("/root//node()"));
1723
byte[] result = out.toByteArray();
1725
String s = new String(out.toByteArray(), "UTF8");
1726
assertEquals(expected, s);
1731
public void testExclusiveWithInclusiveNamespaces()
1732
throws IOException {
1734
Element pdu = new Element("n0:pdu", "http://a.example");
1735
Element elem1 = new Element("n1:elem1", "http://b.example");
1736
elem1.appendChild("content");
1737
pdu.appendChild(elem1);
1739
String expected = "<n1:elem1 xmlns:n0=\"http://a.example\""
1740
+ " xmlns:n1=\"http://b.example\">content</n1:elem1>";
1741
ByteArrayOutputStream out = new ByteArrayOutputStream();
1742
Canonicalizer canonicalizer = new Canonicalizer(out,
1743
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1745
XPathContext context = new XPathContext("n1", "http://b.example");
1746
Document doc = new Document(pdu);
1747
canonicalizer.setInclusiveNamespacePrefixList("n0");
1748
Nodes subset = doc.query(
1749
"(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]",
1751
canonicalizer.write(subset);
1753
byte[] result = out.toByteArray();
1755
String s = new String(out.toByteArray(), "UTF8");
1756
assertEquals(expected, s);
1761
public void testClearInclusiveNamespacePrefixes()
1762
throws IOException {
1764
Element pdu = new Element("n0:pdu", "http://a.example");
1765
Element elem1 = new Element("n1:elem1", "http://b.example");
1766
elem1.appendChild("content");
1767
pdu.appendChild(elem1);
1769
String expected = "<n1:elem1"
1770
+ " xmlns:n1=\"http://b.example\">content</n1:elem1>";
1771
ByteArrayOutputStream out = new ByteArrayOutputStream();
1772
Canonicalizer canonicalizer = new Canonicalizer(out,
1773
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1775
XPathContext context = new XPathContext("n1", "http://b.example");
1776
Document doc = new Document(pdu);
1777
canonicalizer.setInclusiveNamespacePrefixList("n0");
1778
canonicalizer.setInclusiveNamespacePrefixList(null);
1779
Nodes subset = doc.query(
1780
"(//. | //@* | //namespace::*)[ancestor-or-self::n1:elem1]",
1782
canonicalizer.write(subset);
1784
byte[] result = out.toByteArray();
1786
String s = new String(out.toByteArray(), "UTF8");
1787
assertEquals(expected, s);
1792
public void testExclusive22a() throws ParsingException, IOException {
1794
Builder builder = new Builder();
1795
String input = "<n0:local xmlns:n0='foo:bar' xmlns:n3='ftp://example.org'>" +
1796
"<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">"
1797
+ "<n3:stuff xmlns:n3=\"ftp://example.org\"/></n1:elem2></n0:local>";
1798
Document doc = builder.build(input, null);
1800
String expected = "<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">" +
1801
"<n3:stuff xmlns:n3=\"ftp://example.org\"></n3:stuff></n1:elem2>";
1802
ByteArrayOutputStream out = new ByteArrayOutputStream();
1803
Canonicalizer canonicalizer = new Canonicalizer(out,
1804
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1806
XPathContext context = new XPathContext("n1", "http://example.net");
1807
canonicalizer.write(doc.query(
1808
" (//. | //@* | //namespace::*)[ancestor-or-self::n1:elem2]",
1811
byte[] result = out.toByteArray();
1813
String s = new String(out.toByteArray(), "UTF8");
1814
assertEquals(expected, s);
1819
public void testExclusive22b() throws ParsingException, IOException {
1821
Builder builder = new Builder();
1822
String input = "<n2:pdu xmlns:n1='http://example.com' "
1823
+ "xmlns:n2='http://foo.example' xml:lang='fr' xml:space='retain'>"
1824
+ "<n1:elem2 xmlns:n1='http://example.net' xml:lang='en'>"
1825
+ "<n3:stuff xmlns:n3='ftp://example.org'/></n1:elem2></n2:pdu>";
1826
Document doc = builder.build(input, null);
1828
String expected = "<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\">"
1829
+ "<n3:stuff xmlns:n3=\"ftp://example.org\"></n3:stuff></n1:elem2>";
1830
ByteArrayOutputStream out = new ByteArrayOutputStream();
1831
Canonicalizer canonicalizer = new Canonicalizer(out,
1832
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS);
1834
XPathContext context = new XPathContext("n1", "http://example.net");
1835
canonicalizer.write(doc.query(" (//. | //@* | //namespace::*)[ancestor-or-self::n1:elem2]", context));
1837
byte[] result = out.toByteArray();
1839
String s = new String(out.toByteArray(), "UTF8");
1840
assertEquals(expected, s);
1845
// compare to output generated by Apache XML Security code
1846
public void testExclusiveXMLConformanceTestSuiteDocuments()
1847
throws ParsingException, IOException {
1849
File masterList = new File(canonical, "xmlconf");
1850
masterList = new File(masterList, "xmlconf.xml");
1851
if (masterList.exists()) {
1852
Document xmlconf = builder.build(masterList);
1853
Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
1854
processExclusiveTestCases(testcases);
1860
// xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
1862
private void processExclusiveTestCases(Elements testcases)
1863
throws ParsingException, IOException {
1865
for (int i = 0; i < testcases.size(); i++) {
1866
Element testcase = testcases.get(i);
1867
Elements tests = testcase.getChildElements("TEST");
1868
processExclusiveTests(tests);
1869
Elements level2 = testcase.getChildElements("TESTCASES");
1870
// need to be recursive to handle recursive IBM test cases
1871
processExclusiveTestCases(level2);
1877
private void processExclusiveTests(Elements tests)
1878
throws ParsingException, IOException {
1880
for (int i = 0; i < tests.size(); i++) {
1881
Element test = tests.get(i);
1882
String namespace = test.getAttributeValue("NAMESPACE");
1883
if ("no".equals(namespace)) continue;
1884
String type = test.getAttributeValue("TYPE");
1885
if ("not-wf".equals(type)) continue;
1886
String uri = test.getAttributeValue("URI");
1887
String base = test.getBaseURI();
1888
// Hack because URIUtil isn't public; and I don't want to
1889
// depend on 1.4 only java.net.URI
1890
Element parent = new Element("e");
1891
parent.setBaseURI(base);
1892
Element child = new Element("a");
1893
child.addAttribute(new Attribute("xml:base",
1894
"http://www.w3.org/XML/1998/namespace", uri));
1895
parent.appendChild(child);
1896
String resolvedURI = child.getBaseURI();
1898
Document doc = builder.build(resolvedURI);
1899
ByteArrayOutputStream out = new ByteArrayOutputStream();
1901
Canonicalizer serializer = new Canonicalizer(
1903
Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION_WITH_COMMENTS
1905
serializer.write(doc);
1910
byte[] actual = out.toByteArray();
1912
File input = new File(resolvedURI.substring(5) + ".exc");
1913
byte[] expected = new byte[(int) input.length()];
1914
DataInputStream in = new DataInputStream(
1915
new BufferedInputStream(new FileInputStream(input)));
1917
in.readFully(expected);
1923
assertEquals(resolvedURI, new String(expected, "UTF-8"), new String(actual, "UTF-8"));
1930
public void testCanonicalizeAttribute() throws IOException {
1932
Attribute att = new Attribute("pre:foo", "http://www.example.org", "value");
1933
ByteArrayOutputStream out = new ByteArrayOutputStream();
1935
Canonicalizer serializer = new Canonicalizer(out);
1936
serializer.write(att);
1941
byte[] actual = out.toByteArray();
1942
byte[] expected = " pre:foo=\"value\"".getBytes("UTF-8");
1943
assertEquals(expected, actual);
1948
public void testCanonicalizeNamespace() throws IOException {
1950
Element element = new Element("pre:foo", "http://www.example.org");
1951
Nodes namespaces = element.query("namespace::pre");
1952
Namespace ns = (Namespace) namespaces.get(0);
1953
ByteArrayOutputStream out = new ByteArrayOutputStream();
1955
Canonicalizer serializer = new Canonicalizer(out);
1956
serializer.write(ns);
1961
byte[] actual = out.toByteArray();
1962
byte[] expected = " xmlns:pre=\"http://www.example.org\"".getBytes("UTF-8");
1963
assertEquals(expected, actual);
1969
public void testCanonicalizeDefaultNamespace() throws IOException {
1971
Element element = new Element("foo", "http://www.example.org");
1972
Nodes namespaces = element.query("namespace::*");
1973
Namespace ns = (Namespace) namespaces.get(0);
1974
if (ns.getPrefix().equals("xml")) ns = (Namespace) namespaces.get(1);
1975
ByteArrayOutputStream out = new ByteArrayOutputStream();
1977
Canonicalizer serializer = new Canonicalizer(out);
1978
serializer.write(ns);
1983
byte[] actual = out.toByteArray();
1984
byte[] expected = " xmlns=\"http://www.example.org\"".getBytes("UTF-8");
1985
assertEquals(expected, actual);
1990
public void testCanonicalizeXMLNamespace() throws IOException {
1992
Element element = new Element("foo");
1993
Nodes namespaces = element.query("namespace::*");
1994
Namespace ns = (Namespace) namespaces.get(0);
1995
ByteArrayOutputStream out = new ByteArrayOutputStream();
1997
Canonicalizer serializer = new Canonicalizer(out);
1998
serializer.write(ns);
2003
byte[] actual = out.toByteArray();
2005
= " xmlns:xml=\"http://www.w3.org/XML/1998/namespace\"".getBytes("UTF-8");
2006
assertEquals(expected, actual);
2011
public void testCanonicalizeElement() throws IOException {
2013
Element element = new Element("pre:foo", "http://www.example.org");
2014
element.appendChild(" value \n value");
2015
ByteArrayOutputStream out = new ByteArrayOutputStream();
2017
Canonicalizer serializer = new Canonicalizer(out);
2018
serializer.write(element);
2023
byte[] actual = out.toByteArray();
2025
"<pre:foo xmlns:pre=\"http://www.example.org\"> value \n value</pre:foo>"
2027
assertEquals(expected, actual);
2032
public void testDontPutElementInDocument() throws IOException {
2035
Element element = new Element("pre:foo", "http://www.example.org");
2036
assertNull(element.getDocument());
2037
ByteArrayOutputStream out = new ByteArrayOutputStream();
2039
Canonicalizer serializer = new Canonicalizer(out);
2040
serializer.write(element);
2041
assertNull(element.getDocument());
2050
public void testCanonicalizeElementInDocument() throws IOException {
2052
Element root = new Element("root");
2053
Document doc = new Document(root);
2054
Element element = new Element("pre:foo", "http://www.example.org");
2055
root.appendChild(element);
2056
element.appendChild(" value \n value");
2057
ByteArrayOutputStream out = new ByteArrayOutputStream();
2059
Canonicalizer serializer = new Canonicalizer(out);
2060
serializer.write(element);
2065
byte[] actual = out.toByteArray();
2067
"<pre:foo xmlns:pre=\"http://www.example.org\"> value \n value</pre:foo>"
2069
assertEquals(expected, actual);
2074
public void testNoInfiniteLoopWhenWritingADocumentlessElement() throws IOException {
2076
Element root = new Element("root");
2077
Element a = new Element("a");
2078
root.appendChild(a);
2079
Element b = new Element("b");
2082
ByteArrayOutputStream out = new ByteArrayOutputStream();
2084
Canonicalizer serializer = new Canonicalizer(out);
2085
serializer.write(b);
2090
byte[] actual = out.toByteArray();
2094
assertEquals(expected, actual);
2099
public void testExclusiveCanonicalizeElementInDocument() throws IOException {
2101
Element root = new Element("root");
2102
Document doc = new Document(root);
2103
Element element = new Element("pre:foo", "http://www.example.org");
2104
root.appendChild(element);
2105
element.appendChild(" value \n value");
2106
ByteArrayOutputStream out = new ByteArrayOutputStream();
2108
Canonicalizer serializer = new Canonicalizer(out, Canonicalizer.EXCLUSIVE_XML_CANONICALIZATION);
2109
serializer.write(element);
2114
byte[] actual = out.toByteArray();
2116
"<pre:foo xmlns:pre=\"http://www.example.org\"> value \n value</pre:foo>"
2118
assertEquals(expected, actual);
2123
public void testCanonicalizeDocumentTypeDeclaration() throws IOException {
2125
DocType doctype = new DocType("root", "http://www.example.org");
2126
ByteArrayOutputStream out = new ByteArrayOutputStream();
2128
Canonicalizer serializer = new Canonicalizer(out);
2129
serializer.write(doctype);
2134
byte[] actual = out.toByteArray();
2135
assertEquals(0, actual.length);
2140
public void testCanonicalizeProcessingInstruction() throws IOException {
2142
ProcessingInstruction pi = new ProcessingInstruction("target", "value \n value");
2143
ByteArrayOutputStream out = new ByteArrayOutputStream();
2145
Canonicalizer serializer = new Canonicalizer(out);
2146
serializer.write(pi);
2151
byte[] actual = out.toByteArray();
2152
byte[] expected = "<?target value \n value?>".getBytes("UTF-8");
2153
assertEquals(expected, actual);
2158
public void testCanonicalizeText() throws IOException {
2160
Text c = new Text(" pre:foo \n ");
2161
ByteArrayOutputStream out = new ByteArrayOutputStream();
2163
Canonicalizer serializer = new Canonicalizer(out);
2164
serializer.write(c);
2169
byte[] actual = out.toByteArray();
2170
byte[] expected = " pre:foo \n ".getBytes("UTF-8");
2171
assertEquals(expected, actual);
2177
public void testCanonicalizeComment() throws IOException {
2179
Comment c = new Comment("pre:foo");
2180
ByteArrayOutputStream out = new ByteArrayOutputStream();
2182
Canonicalizer serializer = new Canonicalizer(out);
2183
serializer.write(c);
2188
byte[] actual = out.toByteArray();
2189
byte[] expected = "<!--pre:foo-->".getBytes("UTF-8");
2190
assertEquals(expected, actual);
2195
public void testUnsupportedAlgorithm() throws IOException {
2197
ByteArrayOutputStream out = new ByteArrayOutputStream();
2199
new Canonicalizer(out, "http://www.example.org/canonical");
2200
fail("Allowed unrecognized algorithm");
2202
catch (CanonicalizationException success) {
2203
assertNotNull(success.getMessage());
2212
public void testCanonicalizeDetachedNodes() throws IOException {
2214
ByteArrayOutputStream out = new ByteArrayOutputStream();
2215
Element e = new Element("test");
2216
Nodes nodes = new Nodes(e);
2217
Canonicalizer serializer = new Canonicalizer(out);
2219
serializer.write(nodes);
2220
fail("Canonicalized detached node");
2222
catch (CanonicalizationException success) {
2223
assertNotNull(success.getMessage());
2232
public void testCanonicalizeNodesFromTwoDocuments() throws IOException {
2234
ByteArrayOutputStream out = new ByteArrayOutputStream();
2235
Element e1 = new Element("test");
2237
Element e2 = new Element("test");
2239
Nodes nodes = new Nodes(e1);
2241
Canonicalizer serializer = new Canonicalizer(out);
2243
serializer.write(nodes);
2244
fail("Canonicalized multiple document nodes");
2246
catch (CanonicalizationException success) {
2247
assertNotNull(success.getMessage());
2258
* Asserts that two byte arrays are equal. If the two arrays are
2259
* not equal a <code>ComparisonFailure</code> is thrown. Two
2260
* arrays are equal if and only if they have the same length,
2261
* and each item in the expected array is equal to the
2262
* corresponding item in the actual array.
2265
* @param expected the byte array the test should produce
2266
* @param actual the byte array the test does produce
2268
private void assertEquals(byte[] expected, byte[] actual) {
2270
if (expected == null && actual == null) {
2273
// what if one is null and the other isn't????
2274
assertEquals(expected.length, actual.length);
2275
for (int i = 0; i < actual.length; i++) {
2276
assertEquals(expected[i], actual[i]);
2282
// This class forces IOExceptions when writing
2283
private static class UnwriteableOutputStream extends OutputStream {
2285
public void write(int b) throws IOException {
2286
throw new IOException();
2292
public void testDetachElementWhenExceptionIsThrown() {
2294
Element e = new Element("a");
2295
Canonicalizer canonicalizer = new Canonicalizer(new UnwriteableOutputStream());
2297
canonicalizer.write(e);
2299
catch (IOException ex) {
2301
assertNull(e.getParent());