1 21 22 package nu.xom; 23 24 44 public class Attribute extends Node { 45 46 private String localName; 47 private String prefix; 48 private String URI; 49 private String value = ""; 50 private Type type; 51 52 53 69 public Attribute(String localName, String value) { 70 this(localName, "", value, Type.UNDECLARED); 71 } 72 73 74 93 public Attribute(String localName, String value, Type type) { 94 this(localName, "", value, type); 95 } 96 97 98 117 public Attribute(String name, String URI, String value) { 118 this(name, URI, value, Type.UNDECLARED); 119 } 120 121 122 143 public Attribute( 144 String name, String URI, String value, Type type) { 145 146 prefix = ""; 147 String localName = name; 148 if (name.indexOf(':') > 0) { 153 prefix = name.substring(0, name.indexOf(':')); 154 localName = name.substring(name.indexOf(':') + 1); 155 } 156 157 try { 158 _setLocalName(localName); 159 } 160 catch (IllegalNameException ex) { 161 ex.setData(name); 162 throw ex; 163 } 164 _setNamespace(prefix, URI); 165 _setValue(value); 166 _setType(type); 167 168 } 169 170 171 179 public Attribute(Attribute attribute) { 180 181 this.localName = attribute.localName; 183 this.prefix = attribute.prefix; 184 this.URI = attribute.URI; 185 this.value = attribute.value; 186 this.type = attribute.type; 187 188 } 189 190 191 private Attribute() {} 192 193 static Attribute build( 194 String name, String URI, String value, Type type) { 195 196 Attribute result = new Attribute(); 197 198 String prefix = ""; 199 String localName = name; 200 if (name.indexOf(':') >= 0) { 201 prefix = name.substring(0, name.indexOf(':')); 202 localName = name.substring(name.indexOf(':') + 1); 203 } 204 205 result.localName = localName; 206 result.prefix = prefix; 207 result.type = type; 208 result.URI = URI; 209 result.value = value; 210 211 return result; 212 213 } 214 215 216 225 public final Type getType() { 226 return type; 227 } 228 229 230 238 public void setType(Type type) { 239 _setType(type); 240 } 241 242 243 private void _setType(Type type) { 244 this.type = type; 245 } 246 247 248 259 public final String getValue() { 260 return value; 261 } 262 263 264 280 public void setValue(String value) { 281 _setValue(value); 282 } 283 284 285 private void _setValue(String value) { 286 Verifier.checkPCDATA(value); 287 this.value = value; 288 } 289 290 291 299 public final String getLocalName() { 300 return localName; 301 } 302 303 304 315 public void setLocalName(String localName) { 316 _setLocalName(localName); 317 } 318 319 320 private void _setLocalName(String localName) { 321 Verifier.checkNCName(localName); 322 if (localName.equals("xmlns")) { 323 throw new IllegalNameException("The Attribute class is not" 324 + " used for namespace declaration attributes."); 325 } 326 this.localName = localName; 327 } 328 329 330 338 public final String getQualifiedName() { 339 if (prefix.length() == 0) return localName; 340 else return prefix + ":" + localName; 341 } 342 343 344 352 public final String getNamespaceURI() { 353 return URI; 354 } 355 356 357 366 public final String getNamespacePrefix() { 367 return prefix; 368 } 369 370 371 398 public void setNamespace(String prefix, String URI) { 399 _setNamespace(prefix, URI); 400 } 401 402 403 private void _setNamespace(String prefix, String URI) { 404 405 if (URI == null) URI = ""; 406 if (prefix == null) prefix = ""; 407 408 if (prefix.equals("xmlns")) { 409 throw new IllegalNameException( 410 "Attribute objects are not used to represent " 411 + " namespace declarations"); 412 } 413 else if (prefix.equals("xml") 414 && !(URI.equals("http://www.w3.org/XML/1998/namespace"))) { 415 throw new NamespaceConflictException( 416 "Wrong namespace URI for xml prefix: " + URI); 417 } 418 else if (URI.equals("http://www.w3.org/XML/1998/namespace") 419 && !prefix.equals("xml")) { 420 throw new NamespaceConflictException( 421 "Wrong prefix for the XML namespace: " + prefix); 422 } 423 else if (prefix.length() == 0) { 424 if (URI.length() == 0) { 425 this.prefix = ""; 426 this.URI = ""; 427 return; 428 } 429 else { 430 throw new NamespaceConflictException( 431 "Unprefixed attribute " + this.localName 432 + " cannot be in default namespace " + URI); 433 } 434 } 435 else if (URI.length() == 0) { 436 throw new NamespaceConflictException( 437 "Attribute prefixes must be declared."); 438 } 439 440 ParentNode parent = this.getParent(); 441 if (parent != null) { 442 Element element = (Element) parent; 444 String currentURI = element.getLocalNamespaceURI(prefix); 445 if (currentURI != null && !currentURI.equals(URI)) { 446 throw new NamespaceConflictException( 447 "New prefix " + prefix 448 + "conflicts with existing namespace declaration" 449 ); 450 } 451 } 452 453 454 Verifier.checkAbsoluteURIReference(URI); 455 Verifier.checkNCName(prefix); 456 457 this.URI = URI; 458 this.prefix = prefix; 459 460 } 461 462 463 476 public final Node getChild(int position) { 477 throw new IndexOutOfBoundsException ( 478 "Attributes do not have children" 479 ); 480 } 481 482 483 490 public final int getChildCount() { 491 return 0; 492 } 493 494 495 504 public Node copy() { 505 return new Attribute(this); 506 } 507 508 509 517 public final String toXML() { 518 return getQualifiedName() + "=\"" + escapeText(value) + "\""; 526 } 527 528 529 540 public final String toString() { 541 return "[" + getClass().getName() + ": " 542 + getQualifiedName() + "=\"" 543 + Text.escapeLineBreaksAndTruncate(getValue()) + "\"]"; 544 } 545 546 547 private static String escapeText(String s) { 548 549 int length = s.length(); 550 StringBuffer result = new StringBuffer (length+12); 552 for (int i = 0; i < length; i++) { 553 char c = s.charAt(i); 554 switch (c) { 555 case '\t': 556 result.append("	"); 557 break; 558 case '\n': 559 result.append("
"); 560 break; 561 case 11: 562 break; 564 case 12: 565 break; 567 case '\r': 568 result.append("
"); 569 break; 570 case 14: 571 break; 573 case 15: 574 break; 576 case 16: 577 break; 579 case 17: 580 break; 582 case 18: 583 break; 585 case 19: 586 break; 588 case 20: 589 break; 591 case 21: 592 break; 594 case 22: 595 break; 597 case 23: 598 break; 600 case 24: 601 break; 603 case 25: 604 break; 606 case 26: 607 break; 609 case 27: 610 break; 612 case 28: 613 break; 615 case 29: 616 break; 618 case 30: 619 break; 621 case 31: 622 break; 624 case ' ': 625 result.append(' '); 626 break; 627 case '!': 628 result.append('!'); 629 break; 630 case '"': 631 result.append("""); 632 break; 633 case '#': 634 result.append('#'); 635 break; 636 case '$': 637 result.append('$'); 638 break; 639 case '%': 640 result.append('%'); 641 break; 642 case '&': 643 result.append("&"); 644 break; 645 case '\'': 646 result.append('\''); 647 break; 648 case '(': 649 result.append('('); 650 break; 651 case ')': 652 result.append(')'); 653 break; 654 case '*': 655 result.append('*'); 656 break; 657 case '+': 658 result.append('+'); 659 break; 660 case ',': 661 result.append(','); 662 break; 663 case '-': 664 result.append('-'); 665 break; 666 case '.': 667 result.append('.'); 668 break; 669 case '/': 670 result.append('/'); 671 break; 672 case '0': 673 result.append('0'); 674 break; 675 case '1': 676 result.append('1'); 677 break; 678 case '2': 679 result.append('2'); 680 break; 681 case '3': 682 result.append('3'); 683 break; 684 case '4': 685 result.append('4'); 686 break; 687 case '5': 688 result.append('5'); 689 break; 690 case '6': 691 result.append('6'); 692 break; 693 case '7': 694 result.append('7'); 695 break; 696 case '8': 697 result.append('8'); 698 break; 699 case '9': 700 result.append('9'); 701 break; 702 case ':': 703 result.append(':'); 704 break; 705 case ';': 706 result.append(';'); 707 break; 708 case '<': 709 result.append("<"); 710 break; 711 case '=': 712 result.append('='); 713 break; 714 case '>': 715 result.append(">"); 716 break; 717 default: 718 result.append(c); 719 } 720 } 721 return result.toString(); 722 723 } 724 725 726 boolean isAttribute() { 727 return true; 728 } 729 730 731 751 public static final class Type { 752 753 761 public static final Type CDATA = new Type(1); 762 763 774 public static final Type ID = new Type(2); 775 776 786 public static final Type IDREF = new Type(3); 787 788 799 public static final Type IDREFS = new Type(4); 800 801 810 public static final Type NMTOKEN = new Type(5); 811 812 822 public static final Type NMTOKENS = new Type(6); 823 824 825 835 public static final Type NOTATION = new Type(7); 836 837 847 public static final Type ENTITY = new Type(8); 848 849 859 public static final Type ENTITIES = new Type(9); 860 861 877 public static final Type ENUMERATION = new Type(10); 878 879 893 public static final Type UNDECLARED = new Type(0); 894 895 896 904 public String getName() { 905 906 switch (type) { 907 case 0: 908 return "UNDECLARED"; 909 case 1: 910 return "CDATA"; 911 case 2: 912 return "ID"; 913 case 3: 914 return "IDREF"; 915 case 4: 916 return "IDREFS"; 917 case 5: 918 return "NMTOKEN"; 919 case 6: 920 return "NMTOKENS"; 921 case 7: 922 return "NOTATION"; 923 case 8: 924 return "ENTITY"; 925 case 9: 926 return "ENTITIES"; 927 case 10: 928 return "ENUMERATION"; 929 default: 930 throw new RuntimeException ( 931 "Bug in XOM: unexpected attribute type: " + type); 932 } 933 934 } 935 936 937 private int type; 938 939 private Type(int type) { 940 this.type = type; 941 } 942 943 944 953 public int hashCode() { 954 return this.type; 955 } 956 957 958 972 public boolean equals(Object o) { 973 974 if (o == this) return true; 975 if (o == null) return false; 976 if (this.hashCode() != o.hashCode()) return false; 977 if (!o.getClass().getName().equals("nu.xom.Attribute.Type")) { 978 return false; 979 } 980 return true; 981 982 } 983 984 985 995 public String toString() { 996 997 StringBuffer result 998 = new StringBuffer ("[Attribute.Type: "); 999 result.append(getName()); 1000 result.append("]"); 1001 return result.toString(); 1002 1003 } 1004 1005 1006 } 1007 1008 1009} 1010 | Popular Tags |