1 21 22 package nu.xom; 23 24 25 68 public class DocType extends Node { 69 70 71 private String rootName; 72 private String systemID; 73 private String publicID; 74 private String internalDTDSubset = ""; 76 77 78 98 public DocType( 99 String rootElementName, String publicID, String systemID) { 100 _setRootElementName(rootElementName); 101 _setSystemID(systemID); 102 _setPublicID(publicID); 103 } 104 105 106 122 public DocType(String rootElementName, String systemID) { 123 this(rootElementName, null, systemID); 124 } 125 126 127 139 public DocType(String rootElementName) { 140 this(rootElementName, null, null); 141 } 142 143 144 152 public DocType(DocType doctype) { 153 this.internalDTDSubset = doctype.internalDTDSubset; 154 this.publicID = doctype.publicID; 155 this.systemID = doctype.systemID; 156 this.rootName = doctype.rootName; 157 } 158 159 160 private DocType() {} 161 162 static DocType build( 163 String rootElementName, String publicID, String systemID) { 164 DocType result = new DocType(); 165 result.publicID = publicID; 166 result.systemID = systemID; 167 result.rootName = rootElementName; 168 return result; 169 } 170 171 172 181 public final String getRootElementName() { 182 return rootName; 183 } 184 185 186 199 public void setRootElementName(String name) { 200 _setRootElementName(name); 201 } 202 203 204 private void _setRootElementName(String name) { 205 Verifier.checkXMLName(name); 206 this.rootName = name; 207 } 208 209 210 219 public final String getInternalDTDSubset() { 220 return internalDTDSubset; 221 } 222 223 224 final void setInternalDTDSubset(String internalSubset) { 225 this.internalDTDSubset = internalSubset; 226 } 227 228 229 238 public final String getPublicID() { 239 return publicID; 240 } 241 242 257 public void setPublicID(String id) { 258 _setPublicID(id); 259 } 260 261 262 private void _setPublicID(String id) { 263 264 if (systemID == null && id != null) { 265 throw new WellformednessException( 266 "Cannot have a public ID without a system ID" 267 ); 268 } 269 270 if (id != null) { 271 int length = id.length(); 272 if (length != 0) { 273 if (Verifier.isXMLSpaceCharacter(id.charAt(0))) { 274 throw new IllegalDataException("Initial white space " 275 + "in public IDs is not round trippable."); 276 } 277 if (Verifier.isXMLSpaceCharacter(id.charAt(length - 1))) { 278 throw new IllegalDataException("Trailing white space " 279 + "in public IDs is not round trippable."); 280 } 281 282 for (int i = 0; i < length; i++) { 283 char c = id.charAt(i); 284 if (!isXMLPublicIDCharacter(c)) { 285 throw new IllegalDataException("The character 0x" 286 + Integer.toHexString(c) 287 + " is not allowed in public IDs"); 288 } 289 if (c == ' ' && id.charAt(i-1) == ' ') { 290 throw new IllegalDataException("Multiple consecutive " 291 + "spaces in public IDs are not round trippable."); 292 } 293 } 294 } 295 } 296 this.publicID = id; 297 298 } 299 300 301 309 public final String getSystemID() { 310 return systemID; 311 } 312 313 314 331 public void setSystemID(String id) { 332 _setSystemID(id); 333 } 334 335 336 private void _setSystemID(String id) { 337 338 if (id == null && publicID != null) { 339 throw new WellformednessException( 340 "Cannot remove system ID without removing public ID first" 341 ); 342 } 343 344 if (id != null) { 345 346 Verifier.checkURIReference(id); 347 348 if (id.indexOf('#') != -1) { 349 MalformedURIException ex = new MalformedURIException( 350 "System literals cannot contain fragment identifiers" 351 ); 352 ex.setData(id); 353 throw ex; 354 } 355 } 356 357 this.systemID = id; 358 359 } 360 361 362 370 public final String getValue() { 371 return ""; 372 } 373 374 375 389 public final Node getChild(int position) { 390 throw new IndexOutOfBoundsException ( 391 "LeafNodes do not have children"); 392 } 393 394 395 403 public final int getChildCount() { 404 return 0; 405 } 406 407 408 418 public final String toString() { 419 return "[" + getClass().getName() + ": " + rootName + "]"; 420 } 421 422 423 434 public Node copy() { 435 return new DocType(this); 436 } 437 438 439 450 public final String toXML() { 451 452 StringBuffer result = new StringBuffer (); 453 result.append("<!DOCTYPE "); 454 result.append(rootName); 455 if (publicID != null) { 456 result.append(" PUBLIC \""); 457 result.append(publicID); 458 result.append("\" \""); 459 result.append(systemID); 460 result.append('"'); 461 } 462 else if (systemID != null) { 463 result.append(" SYSTEM \""); 464 result.append(systemID); 465 result.append('"'); 466 } 467 468 if (internalDTDSubset.length() != 0) { 469 result.append(" [\n"); 470 result.append(internalDTDSubset); 471 result.append(']'); 472 } 473 474 result.append(">"); 475 return result.toString(); 476 } 477 478 479 boolean isDocType() { 480 return true; 481 } 482 483 484 private static boolean isXMLPublicIDCharacter(char c) { 485 486 switch(c) { 491 case ' ': return true; 492 case '!': return true; 493 case '"': return false; 494 case '#': return true; 495 case '$': return true; 496 case '%': return true; 497 case '&': return false; 498 case '\'': return true; 499 case '(': return true; 500 case ')': return true; 501 case '*': return true; 502 case '+': return true; 503 case ',': return true; 504 case '-': return true; 505 case '.': return true; 506 case '/': return true; 507 case '0': return true; 508 case '1': return true; 509 case '2': return true; 510 case '3': return true; 511 case '4': return true; 512 case '5': return true; 513 case '6': return true; 514 case '7': return true; 515 case '8': return true; 516 case '9': return true; 517 case ':': return true; 518 case ';': return true; 519 case '<': return false; 520 case '=': return true; 521 case '>': return false; 522 case '?': return true; 523 case '@': return true; 524 case 'A': return true; 525 case 'B': return true; 526 case 'C': return true; 527 case 'D': return true; 528 case 'E': return true; 529 case 'F': return true; 530 case 'G': return true; 531 case 'H': return true; 532 case 'I': return true; 533 case 'J': return true; 534 case 'K': return true; 535 case 'L': return true; 536 case 'M': return true; 537 case 'N': return true; 538 case 'O': return true; 539 case 'P': return true; 540 case 'Q': return true; 541 case 'R': return true; 542 case 'S': return true; 543 case 'T': return true; 544 case 'U': return true; 545 case 'V': return true; 546 case 'W': return true; 547 case 'X': return true; 548 case 'Y': return true; 549 case 'Z': return true; 550 case '[': return false; 551 case '\\': return false; 552 case ']': return false; 553 case '^': return false; 554 case '_': return true; 555 case '`': return false; 556 case 'a': return true; 557 case 'b': return true; 558 case 'c': return true; 559 case 'd': return true; 560 case 'e': return true; 561 case 'f': return true; 562 case 'g': return true; 563 case 'h': return true; 564 case 'i': return true; 565 case 'j': return true; 566 case 'k': return true; 567 case 'l': return true; 568 case 'm': return true; 569 case 'n': return true; 570 case 'o': return true; 571 case 'p': return true; 572 case 'q': return true; 573 case 'r': return true; 574 case 's': return true; 575 case 't': return true; 576 case 'u': return true; 577 case 'v': return true; 578 case 'w': return true; 579 case 'x': return true; 580 case 'y': return true; 581 case 'z': return true; 582 } 583 584 return false; 585 586 } 587 588 589 } | Popular Tags |