1 21 22 package nu.xom.tests; 23 24 import java.io.IOException ; 25 26 import org.xml.sax.SAXException ; 27 import org.xml.sax.XMLFilter ; 28 import org.xml.sax.helpers.XMLFilterImpl ; 29 import org.xml.sax.helpers.XMLReaderFactory ; 30 31 import nu.xom.Builder; 32 import nu.xom.DocType; 33 import nu.xom.Document; 34 import nu.xom.IllegalDataException; 35 import nu.xom.IllegalNameException; 36 import nu.xom.ParsingException; 37 import nu.xom.ValidityException; 38 import nu.xom.WellformednessException; 39 40 49 public class DocTypeTest extends XOMTestCase { 50 51 52 public DocTypeTest(String name) { 53 super(name); 54 } 55 56 57 String name = "MyName"; 58 String systemID = "http://www.w3.org/TR/some.dtd"; 59 String publicID = "-//Me//some public ID"; 60 61 62 private DocType doctypePublicID; 63 private DocType doctypeSystemID; 64 private DocType doctypeRootOnly; 65 66 67 protected void setUp() { 68 doctypePublicID = new DocType(name, publicID, systemID); 69 doctypeSystemID = new DocType(name, systemID); 70 doctypeRootOnly = new DocType(name); 71 } 72 73 74 public void testToXML() { 75 String expected 76 = "<!DOCTYPE " + name + " PUBLIC \"" 77 + publicID + "\" \"" + systemID + "\">"; 78 assertEquals(expected, doctypePublicID.toXML()); 79 assertEquals( 80 "<!DOCTYPE " + name + " SYSTEM \"" + systemID + "\">", 81 doctypeSystemID.toXML() 82 ); 83 assertEquals( 84 "<!DOCTYPE " + name + ">", 85 doctypeRootOnly.toXML() 86 ); 87 } 88 89 90 public void testToXMLWithInternalDTDSubset() 91 throws ValidityException, ParsingException, IOException { 92 String data = "<?xml version=\"1.0\"?>\n" 93 + "<!DOCTYPE root [\n <!ELEMENT test (#PCDATA)>\n]>" 94 + "\n<test />\n"; 95 Document doc = (new Builder()).build(data, null); 96 String result = doc.toXML(); 97 assertEquals(data, result); 98 99 } 100 101 102 public void testToXMLWithCommentsInInternalDTDSubset() 103 throws ValidityException, ParsingException, IOException { 104 105 String data = "<?xml version=\"1.0\"?>\n" 106 + "<!DOCTYPE root [\n" + 107 " <!--comment-->\n <!ELEMENT test (#PCDATA)>" + 108 "\n <!--comment-->\n]>" 109 + "\n<test />\n"; 110 Document doc = (new Builder()).build(data, null); 111 String result = doc.toXML(); 112 assertEquals(data, result); 113 114 } 115 116 117 public void testToXMLWithCommentsInInternalDTDSubsetAndVerifyingBuilder() 118 throws ValidityException, ParsingException, IOException , SAXException { 119 120 String data = "<?xml version=\"1.0\"?>\n" 121 + "<!DOCTYPE root [\n" + 122 " <!--comment-->\n <!ELEMENT test (#PCDATA)>" + 123 "\n <!--comment-->\n]>" 124 + "\n<test />\n"; 125 XMLFilter filter = new XMLFilterImpl (); 126 filter.setParent(XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser")); 127 Document doc = (new Builder(filter)).build(data, null); 128 String result = doc.toXML(); 129 assertEquals(data, result); 130 131 } 132 133 134 public void testToXMLWithProcessingInstructionsInInternalDTDSubset() 135 throws ValidityException, ParsingException, IOException { 136 137 String data = "<?xml version=\"1.0\"?>\n" 138 + "<!DOCTYPE root [\n" + 139 " <?target data?>\n <!ELEMENT test (#PCDATA)>" + 140 "\n <?target?>\n]>" 141 + "\n<test />\n"; 142 Document doc = (new Builder()).build(data, null); 143 String result = doc.toXML(); 144 assertEquals(data, result); 145 146 } 147 148 149 public void testToXMLWithProcessingInstructionsInInternalDTDSubsetAndNonverifyingBuilder() 150 throws ValidityException, ParsingException, IOException , SAXException { 151 152 String data = "<?xml version=\"1.0\"?>\n" 153 + "<!DOCTYPE root [\n" + 154 " <?target data?>\n <!ELEMENT test (#PCDATA)>" + 155 "\n <?target?>\n]>" 156 + "\n<test />\n"; 157 XMLFilter filter = new XMLFilterImpl (); 158 filter.setParent(XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser")); 159 Document doc = (new Builder(filter)).build(data, null); 160 String result = doc.toXML(); 161 assertEquals(data, result); 162 163 } 164 165 166 public void testInternalDTDSubset() 167 throws ParsingException, IOException { 168 169 String data = "<!DOCTYPE root [ <!ELEMENT root EMPTY> ]><test/>"; 170 Builder builder = new Builder(); 171 Document doc = builder.build(data, "http://www.example.com"); 172 DocType doctype = doc.getDocType(); 173 assertEquals("root", doctype.getRootElementName()); 174 String internalSubset = doctype.getInternalDTDSubset(); 175 assertEquals(" <!ELEMENT root EMPTY>\n", internalSubset); 176 assertTrue(doctype.toXML().indexOf("[") > 0); 177 assertTrue(doctype.toXML().indexOf("]") > 0); 178 assertTrue(doctype.toXML().indexOf("<!ELEMENT root EMPTY>") > 0); 179 180 } 181 182 183 public void testToString() { 184 185 String expected 186 = "[nu.xom.DocType: " + name + "]"; 187 assertEquals(expected, doctypePublicID.toString()); 188 189 } 190 191 192 public void testConstructor1Arg() { 193 194 String name = "MyName"; 195 DocType doctype = new DocType(name); 196 assertEquals(name, doctype.getRootElementName()); 197 assertEquals("", doctype.getInternalDTDSubset()); 198 assertNull(doctype.getSystemID()); 199 assertNull(doctype.getPublicID()); 200 201 name = "try:MyName"; 203 doctype = new DocType(name); 204 assertEquals("", doctype.getInternalDTDSubset()); 205 assertEquals(name, doctype.getRootElementName()); 206 assertNull(doctype.getSystemID()); 207 assertNull(doctype.getPublicID()); 208 209 try { 211 name = "try MyName"; 212 doctype = new DocType(name); 213 fail("allowed root element name to contain spaces"); 214 } 215 catch (IllegalNameException success) { 216 assertNotNull(success.getMessage()); 217 } 218 219 } 220 221 222 public void testNullRootElementName() { 223 224 try { 225 new DocType((String ) null); 226 fail("Allowed null root element name"); 227 } 228 catch (IllegalNameException success) { 229 assertNotNull(success.getMessage()); 230 } 231 232 } 233 234 235 public void testRootElementNameBeginsWithDigit() { 236 237 try { 238 new DocType("1Data"); 239 fail("Allowed non-namestart character in root element name"); 240 } 241 catch (IllegalNameException success) { 242 assertNotNull(success.getMessage()); 243 } 244 245 } 246 247 248 public void testRootElementNameBeginsWithColon() { 249 250 try { 251 new DocType(":Data"); 252 fail("Allowed colon to begin root element name"); 253 } 254 catch (IllegalNameException success) { 255 assertNotNull(success.getMessage()); 256 } 257 258 } 259 260 261 public void testSetRootElementName() { 262 263 DocType doctype = new DocType("root"); 264 doctype.setRootElementName("newname"); 265 assertEquals("newname", doctype.getRootElementName()); 266 doctype.setRootElementName("new:name"); 267 assertEquals("new:name", doctype.getRootElementName()); 268 try { 269 doctype.setRootElementName(":Data"); 270 fail("Allowed colon to begin root element name"); 271 } 272 catch (IllegalNameException success) { 273 assertNotNull(success.getMessage()); 274 } 275 276 } 277 278 279 public void testEmptyRootElementName() { 280 281 try { 282 new DocType(""); 283 fail("Allowed empty string to be root element name"); 284 } 285 catch (IllegalNameException success) { 286 assertNotNull(success.getMessage()); 287 } 288 289 } 290 291 292 public void testNoChildren() { 293 294 assertEquals(0, doctypePublicID.getChildCount()); 295 assertEquals(0, doctypeSystemID.getChildCount()); 296 assertEquals(0, doctypeRootOnly.getChildCount()); 297 298 try { 299 doctypePublicID.getChild(0); 300 fail("Got zeroth child"); 301 } 302 catch (IndexOutOfBoundsException success) { 303 assertNotNull(success.getMessage()); 304 } 305 306 } 307 308 309 public void testConstructor2Arg() { 310 311 String name = "MyName"; 312 String systemID = "http://www.w3.org/TR/some.dtd"; 313 DocType doctype = new DocType(name, systemID); 314 assertEquals(name, doctype.getRootElementName()); 315 assertEquals("", doctype.getInternalDTDSubset()); 316 assertEquals(systemID, doctype.getSystemID()); 317 assertNull(doctype.getPublicID()); 318 319 name = "try:MyName"; 321 systemID = ""; 322 doctype = new DocType(name, systemID); 323 assertEquals(name, doctype.getRootElementName()); 324 assertEquals("", doctype.getInternalDTDSubset()); 325 assertEquals(systemID, doctype.getSystemID()); 326 assertNull(doctype.getPublicID()); 327 328 } 329 330 331 public void testConstructor3Arg() { 332 333 String name = "MyName"; 334 String systemID = "http://www.w3.org/TR/some.dtd"; 335 String publicID = "-//Me//some public ID"; 336 DocType doctype = new DocType(name, publicID, systemID); 337 assertEquals(name, doctype.getRootElementName()); 338 assertEquals("", doctype.getInternalDTDSubset()); 339 assertEquals(systemID, doctype.getSystemID()); 340 assertEquals(publicID, doctype.getPublicID()); 341 342 } 343 344 345 public void testEmptyStringForPublicID() { 346 347 String name = "MyName"; 348 String systemID = "http://www.w3.org/TR/some.dtd"; 349 String publicID = ""; 350 DocType doctype = new DocType(name, publicID, systemID); 351 assertEquals(name, doctype.getRootElementName()); 352 assertEquals("", doctype.getInternalDTDSubset()); 353 assertEquals(systemID, doctype.getSystemID()); 354 assertEquals(publicID, doctype.getPublicID()); 355 356 } 357 358 359 public void testEmptyStringForSystemID() { 360 361 String name = "MyName"; 362 String systemID = ""; 363 String publicID = "-//Me//some public ID"; 364 DocType doctype = new DocType(name, publicID, systemID); 365 assertEquals(name, doctype.getRootElementName()); 366 assertEquals("", doctype.getInternalDTDSubset()); 367 assertEquals(systemID, doctype.getSystemID()); 368 assertEquals(publicID, doctype.getPublicID()); 369 370 } 371 372 373 public void testIllegalPublicIDs() { 374 375 for (char c = 0; c <= 0x9; c++) { 377 try { 378 checkPublicIDCharacter(c + ""); 379 fail("Allowed bad public ID character " 380 + Integer.toHexString(c)); 381 } 382 catch (WellformednessException success) { 383 assertNotNull(success.getMessage()); 385 } 386 } 387 for (char c = 0xB; c < 0xD; c++) { 388 try { 389 checkPublicIDCharacter(c + ""); 390 fail("Allowed bad public ID character " 391 + Integer.toHexString(c)); 392 } 393 catch (WellformednessException success) { 394 assertNotNull(success.getMessage()); 396 } 397 } 398 for (char c = 0xE; c < 0x20; c++) { 399 try { 400 checkPublicIDCharacter(c + ""); 401 fail("Allowed bad public ID character " 402 + Integer.toHexString(c)); 403 } 404 catch (WellformednessException success) { 405 assertNotNull(success.getMessage()); 407 } 408 } 409 for (char c = '~'; c < 1000; c++) { 410 try { 411 checkPublicIDCharacter(c + ""); 412 fail("Allowed bad public ID character " 413 + Integer.toHexString(c)); 414 } 415 catch (WellformednessException success) { 416 assertNotNull(success.getMessage()); 418 } 419 } 420 421 char[] illegalPunctuationMarks = "<>`^&\"[]{}|\\~".toCharArray(); 422 for (int i = 0; i < illegalPunctuationMarks.length; i++) { 423 char c = illegalPunctuationMarks[i]; 424 try { 425 checkPublicIDCharacter(c + ""); 426 fail("Allowed bad public ID character " 427 + Integer.toHexString(c)); 428 } 429 catch (WellformednessException success) { 430 assertNotNull(success.getMessage()); 432 } 433 } 434 435 } 436 437 438 public void testLegalPublicIDs() { 439 440 checkPublicIDCharacter("-'()+,./:=?;!*#@$_%"); 448 for (char c = 'a'; c <= 'z'; c++) checkPublicIDCharacter(c + ""); 449 for (char c = 'A'; c <= 'Z'; c++) checkPublicIDCharacter(c + ""); 450 for (char c = '0'; c <= '9'; c++) checkPublicIDCharacter(c + ""); 451 452 } 453 454 455 public void testSpaceContainingPublicIDs() { 456 457 try { 460 new DocType("root", " test", "http://www.example.org"); 461 fail("allowed initial space in public ID"); 462 } 463 catch (WellformednessException success) { 464 assertNotNull(success.getMessage()); 465 } 466 467 try { 468 new DocType("root", "test ", "http://www.example.org"); 469 fail("allowed trailing space in public ID"); 470 } 471 catch (WellformednessException success) { 472 assertNotNull(success.getMessage()); 473 } 474 475 try { 476 new DocType("root", "test\ntest", "http://www.example.org"); 477 fail("allowed linefeed public ID"); 478 } 479 catch (WellformednessException success) { 480 assertNotNull(success.getMessage()); 481 } 482 483 try { 484 new DocType("root", "test\rtest", "http://www.example.org"); 485 fail("allowed carriage return in public ID"); 486 } 487 catch (WellformednessException success) { 488 assertNotNull(success.getMessage()); 489 } 490 491 try { 492 new DocType("root", "test\r\ntest", "http://www.example.org"); 493 fail("allowed carriage return linefeed pair public ID"); 494 } 495 catch (WellformednessException success) { 496 assertNotNull(success.getMessage()); 497 } 498 499 try { 500 new DocType("root", "test test", "http://www.example.org"); 501 fail("allowed multiple consecutive spaces in public ID"); 502 } 503 catch (WellformednessException success) { 504 assertNotNull(success.getMessage()); 505 } 506 507 DocType test = new DocType("root", "test test", "http://www.example.org"); 509 assertEquals(test.getPublicID(), "test test"); 510 511 } 512 513 514 public void testSystemIDWithDollarSignAndComma() { 515 516 String systemID = "http://www.example.com/test$red/limit,data.xml"; 517 DocType doctype = new DocType("root", systemID); 518 assertEquals(systemID, doctype.getSystemID()); 519 520 } 521 522 523 public void testSystemIDWithSemicolon() { 524 525 String systemID = "smb://domain;user:pass@server/share/path/to/file"; 526 DocType doctype = new DocType("root", systemID); 527 assertEquals(systemID, doctype.getSystemID()); 528 529 } 530 531 532 public void testIllegalSystemIDs() { 533 534 try { 538 new DocType("test", "http://www.example.com/index.html#test"); 539 fail("Allowed system ID with fragment identifier"); 540 } 541 catch (IllegalDataException success) { 542 assertNotNull(success.getMessage()); 544 } 545 546 try { 547 new DocType("test", "http://www.example.com/index.html#"); 548 fail("Allowed # in system ID"); 549 } 550 catch (IllegalDataException success) { 551 assertNotNull(success.getMessage()); 553 } 554 555 try { 556 new DocType("test", "http://www.example.com/\u00A9.html#"); 557 fail("Allowed non-ASCII character in system ID"); 558 } 559 catch (IllegalDataException success) { 560 assertNotNull(success.getMessage()); 562 } 563 564 try { 565 new DocType("test", "http://www.example.com/\u0007.html#"); 566 fail("Allowed C0 control character in system ID"); 567 } 568 catch (IllegalDataException success) { 569 assertNotNull(success.getMessage()); 571 } 572 573 try { 574 new DocType("test", "test\" and ' in the same ID"); 575 fail("Allowed both \" and ' in system ID"); 576 } 577 catch (IllegalDataException success) { 578 assertNotNull(success.getMessage()); 580 } 581 582 } 583 584 585 void checkPublicIDCharacter(String publicID) { 586 String name = "MyName"; 587 String systemID = "http://www.w3.org/TR/some.dtd"; 588 DocType doctype = new DocType(name, publicID, systemID); 589 assertEquals(publicID, doctype.getPublicID()); 590 } 591 592 593 public void testClone() { 594 595 String name = "MyName"; 596 String systemID = "http://www.w3.org/TR/some.dtd"; 597 String publicID = "-//Me//some public ID"; 598 DocType doctype = new DocType(name, publicID, systemID); 599 600 DocType other = (DocType) doctype.copy(); 601 602 assertEquals( 603 doctype.getRootElementName(), 604 other.getRootElementName()); 605 assertEquals( 606 doctype.getInternalDTDSubset(), 607 other.getInternalDTDSubset() 608 ); 609 assertEquals(doctype.getSystemID(), other.getSystemID()); 610 assertEquals(doctype.getPublicID(), other.getPublicID()); 611 assertTrue(!other.equals(doctype)); 612 613 } 614 615 616 public void testGetters() { 617 618 String name = "MyName"; 619 String systemID = "http://www.w3.org/TR/some.dtd"; 620 String publicID = "-//Me//some public ID"; 621 DocType doctype = new DocType(name, publicID, systemID); 622 623 assertEquals("", doctype.getValue()); 624 625 } 626 627 628 public void testSystemIDRequiredForPublicID() { 629 630 String name = "MyName"; 631 DocType doctype = new DocType(name); 632 633 try { 634 doctype.setPublicID("-//Me//some public ID"); 635 fail("created a doctype with a public ID and no system ID"); 636 } 637 catch (WellformednessException ex) { 638 assertNotNull(ex.getMessage()); 640 } 641 642 } 643 644 645 public void testRemove() { 646 647 String name = "MyName"; 648 String publicID = "-//Me//some public ID"; 649 DocType doctype = 650 new DocType(name, publicID, "http://www.example.com"); 651 652 doctype.setPublicID(null); 653 assertNull(doctype.getPublicID()); 654 doctype.setPublicID(publicID); 655 assertEquals(publicID, doctype.getPublicID()); 656 657 try { 658 doctype.setSystemID(null); 659 fail("removed system ID before removing public ID"); 660 } 661 catch (WellformednessException success) { 662 assertNotNull(success.getMessage()); 663 } 664 665 doctype.setPublicID(null); 666 assertNull(doctype.getPublicID()); 667 doctype.setSystemID(null); 668 assertNull(doctype.getSystemID()); 669 670 } 671 672 673 public void testCarriageReturnInEntityReplacementTextInInternalDTDSubset() 674 throws ParsingException, IOException { 675 676 Builder builder = new Builder(); 677 String data = "<!DOCTYPE root [" 678 + "<!ENTITY CR ' '>" 679 + "]><root/>"; 680 Document doc = builder.build(data, null); 681 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 682 assertTrue(internalDTDSubset.indexOf("<!ENTITY CR \"
\">") > 1); 683 684 } 685 686 687 public void testCarriageReturnInAttributeDefaultValueInInternalDTDSubset() 688 throws ParsingException, IOException { 689 690 Builder builder = new Builder(); 691 String data = "<!DOCTYPE root [" 692 + "<!ATTLIST root attribute CDATA ' '>" 693 + "]><root/>"; 694 Document doc = builder.build(data, null); 695 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 696 assertTrue(internalDTDSubset.indexOf("<!ATTLIST root attribute CDATA \"
\">") > 1); 697 698 } 699 700 701 public void testAmpersandInEntityReplacementTextInInternalDTDSubset() 702 throws ParsingException, IOException { 703 704 Builder builder = new Builder(); 705 String data = "<!DOCTYPE root [" 706 + "<!ENTITY amp2 '&'>" 707 + "]><root/>"; 708 Document doc = builder.build(data, null); 709 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 710 assertTrue(internalDTDSubset.indexOf("<!ENTITY amp2 \"&\">") > 1); 711 712 } 713 714 715 public void testAmpersandInAttributeDefaultValueInInternalDTDSubset() 716 throws ParsingException, IOException { 717 718 Builder builder = new Builder(); 719 String data = "<!DOCTYPE root [" 720 + "<!ATTLIST root attribute CDATA '&'>" 721 + "]><root/>"; 722 Document doc = builder.build(data, null); 723 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 724 assertTrue(internalDTDSubset.indexOf( 725 "<!ATTLIST root attribute CDATA \"&\">") > 1 726 ); 727 728 } 729 730 731 public void testDoubleQuoteInAttributeDefaultValueInInternalDTDSubset() 732 throws ParsingException, IOException { 733 734 Builder builder = new Builder(); 735 String data = "<!DOCTYPE root [" 736 + "<!ATTLIST root attribute CDATA '"'>" 737 + "]><root/>"; 738 Document doc = builder.build(data, null); 739 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 740 assertTrue(internalDTDSubset.indexOf( 741 "<!ATTLIST root attribute CDATA \""\">") > 1 742 ); 743 744 } 745 746 747 public void testSingleQuoteInAttributeDefaultValueInInternalDTDSubset() 748 throws ParsingException, IOException { 749 750 Builder builder = new Builder(); 751 String data = "<!DOCTYPE root [" 752 + "<!ATTLIST root attribute CDATA '''>" 753 + "]><root/>"; 754 Document doc = builder.build(data, null); 755 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 756 assertTrue(internalDTDSubset.indexOf( 757 "<!ATTLIST root attribute CDATA \"'\">") > 1 758 ); 759 760 } 761 762 763 public void testLessThanSignInAttributeDefaultValueInInternalDTDSubset() 764 throws ParsingException, IOException { 765 766 Builder builder = new Builder(); 767 String data = "<!DOCTYPE root [" 768 + "<!ATTLIST root attribute CDATA '<'>" 769 + "]><root/>"; 770 Document doc = builder.build(data, null); 771 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 772 assertTrue(internalDTDSubset.indexOf( 773 "<!ATTLIST root attribute CDATA \"<\">") > 1 774 ); 775 776 } 777 778 779 public void testGreaterThanSignInAttributeDefaultValueInInternalDTDSubset() 780 throws ParsingException, IOException { 781 782 Builder builder = new Builder(); 783 String data = "<!DOCTYPE root [" 784 + "<!ATTLIST root attribute CDATA '>'>" 785 + "]><root/>"; 786 Document doc = builder.build(data, null); 787 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 788 assertTrue(internalDTDSubset.indexOf( 789 "<!ATTLIST root attribute CDATA \">\">") > 1 790 ); 791 792 } 793 794 795 public void testDoubleQuoteInEntityReplacementTextInInternalDTDSubset() 796 throws ParsingException, IOException { 797 798 Builder builder = new Builder(); 799 String data = "<!DOCTYPE root [" 800 + "<!ENTITY q2 '"'>" 801 + "]><root/>"; 802 Document doc = builder.build(data, null); 803 String internalDTDSubset = doc.getDocType().getInternalDTDSubset(); 804 assertTrue(internalDTDSubset.indexOf("<!ENTITY q2 \""\">") > 1); 805 806 } 807 808 809 } | Popular Tags |