1 5 6 package nu.xom.tests; 7 8 import java.io.IOException ; 9 import java.io.OutputStreamWriter ; 10 import java.io.Writer ; 11 import java.util.Enumeration ; 12 import java.util.Hashtable ; 13 14 import org.xml.sax.Attributes ; 15 import org.xml.sax.SAXException ; 16 import org.xml.sax.ext.LexicalHandler ; 17 import org.xml.sax.helpers.AttributesImpl ; 18 import org.xml.sax.helpers.NamespaceSupport ; 19 import org.xml.sax.helpers.XMLFilterImpl ; 20 21 22 41 class XMLWriter extends XMLFilterImpl implements LexicalHandler { 42 43 47 48 55 public XMLWriter() { 56 init(null); 57 } 58 59 60 70 public XMLWriter (Writer writer) { 71 init(writer); 72 } 73 74 84 private void init (Writer writer) { 85 setOutput(writer); 86 nsSupport = new NamespaceSupport (); 87 prefixTable = new Hashtable (); 88 forcedDeclTable = new Hashtable (); 89 doneDeclTable = new Hashtable (); 90 } 91 92 93 97 98 119 public void reset() { 120 elementLevel = 0; 121 prefixCounter = 0; 122 nsSupport.reset(); 123 } 124 125 126 145 public void flush() throws IOException { 146 output.flush(); 147 } 148 149 150 162 public void setOutput (Writer writer) { 163 if (writer == null) { 164 output = new OutputStreamWriter (System.out); 165 } 166 else { 167 output = writer; 168 } 169 } 170 171 172 189 public void setPrefix (String uri, String prefix) { 190 prefixTable.put(uri, prefix); 191 } 192 193 194 205 public String getPrefix (String uri) { 206 return (String )prefixTable.get(uri); 207 } 208 209 public void startPrefixMapping(String prefix, String uri) { 210 this.forceNSDecl(uri, prefix); 211 } 212 213 232 public void forceNSDecl (String uri) { 233 forcedDeclTable.put(uri, Boolean.TRUE); 234 } 235 236 237 253 public void forceNSDecl (String uri, String prefix) { 254 setPrefix(uri, prefix); 255 forceNSDecl(uri); 256 } 257 258 259 263 264 279 public void startDocument() throws SAXException { 280 reset(); 281 write("<?xml version=\"1.0\" standalone=\"yes\"?>\n\n"); 282 super.startDocument(); 283 } 284 285 286 301 public void endDocument() throws SAXException { 302 write('\n'); 303 super.endDocument(); 304 try { 305 flush(); 306 } catch (IOException ex) { 307 throw new SAXException (ex); 308 } 309 } 310 311 312 337 public void startElement (String uri, String localName, 338 String qualifiedName, Attributes atts) throws SAXException { 339 elementLevel++; 340 nsSupport.pushContext(); 341 write('<'); 342 writeName(uri, localName, qualifiedName, true); 343 writeAttributes(atts); 344 if (elementLevel == 1) { 345 forceNSDecls(); 346 } 347 writeNSDecls(); 348 write('>'); 349 super.startElement(uri, localName, qualifiedName, atts); 350 } 351 352 353 377 public void endElement (String uri, String localName, String qualifiedName) 378 throws SAXException { 379 write("</"); 380 writeName(uri, localName, qualifiedName, true); 381 write('>'); 382 if (elementLevel == 1) { 383 write('\n'); 384 } 385 super.endElement(uri, localName, qualifiedName); 386 nsSupport.popContext(); 387 elementLevel--; 388 } 389 390 391 410 public void characters (char[] ch, int start, int length) 411 throws SAXException { 412 writeEsc(ch, start, length, false); 413 super.characters(ch, start, length); 414 } 415 416 417 436 public void ignorableWhitespace (char[] ch, int start, int length) 437 throws SAXException { 438 writeEsc(ch, start, length, false); 439 super.ignorableWhitespace(ch, start, length); 440 } 441 442 443 444 462 public void processingInstruction (String target, String data) 463 throws SAXException { 464 write("<?"); 465 write(target); 466 write(' '); 467 write(data); 468 write("?>"); 469 if (elementLevel < 1) { 470 write('\n'); 471 } 472 super.processingInstruction(target, data); 473 } 474 475 476 477 481 511 public void emptyElement (String uri, String localName, 512 String qualifiedName, Attributes atts) throws SAXException { 513 nsSupport.pushContext(); 514 write('<'); 515 writeName(uri, localName, qualifiedName, true); 516 writeAttributes(atts); 517 if (elementLevel == 1) { 518 forceNSDecls(); 519 } 520 writeNSDecls(); 521 write("/>"); 522 super.startElement(uri, localName, qualifiedName, atts); 523 super.endElement(uri, localName, qualifiedName); 524 } 525 526 527 528 532 533 534 554 public void startElement (String uri, String localName) 555 throws SAXException { 556 startElement(uri, localName, "", EMPTY_ATTS); 557 } 558 559 560 579 public void startElement (String localName) throws SAXException { 580 startElement("", localName, "", EMPTY_ATTS); 581 } 582 583 584 602 public void endElement(String uri, String localName) 603 throws SAXException { 604 endElement(uri, localName, ""); 605 } 606 607 608 626 public void endElement(String localName) throws SAXException { 627 endElement("", localName, ""); 628 } 629 630 631 650 public void emptyElement (String uri, String localName) 651 throws SAXException { 652 emptyElement(uri, localName, "", EMPTY_ATTS); 653 } 654 655 656 676 public void emptyElement (String localName) throws SAXException { 677 emptyElement("", localName, "", EMPTY_ATTS); 678 } 679 680 681 710 public void dataElement (String uri, String localName, 711 String qualifiedName, Attributes atts, String content) 712 throws SAXException { 713 startElement(uri, localName, qualifiedName, atts); 714 characters(content); 715 endElement(uri, localName, qualifiedName); 716 } 717 718 719 747 public void dataElement(String uri, String localName, String content) 748 throws SAXException { 749 dataElement(uri, localName, "", EMPTY_ATTS, content); 750 } 751 752 753 782 public void dataElement (String localName, String content) 783 throws SAXException { 784 dataElement("", localName, "", EMPTY_ATTS, content); 785 } 786 787 802 public void characters(String data) throws SAXException { 803 char[] ch = data.toCharArray(); 804 characters(ch, 0, ch.length); 805 } 806 807 808 809 813 814 824 private void forceNSDecls() { 825 Enumeration prefixes = forcedDeclTable.keys(); 826 while (prefixes.hasMoreElements()) { 827 String prefix = (String )prefixes.nextElement(); 828 doPrefix(prefix, null, true); 829 } 830 } 831 832 833 848 private String doPrefix (String uri, String qName, boolean isElement) { 849 String defaultNS = nsSupport.getURI(""); 850 if ("".equals(uri)) { 851 if (isElement && defaultNS != null) 852 nsSupport.declarePrefix("", ""); 853 return null; 854 } 855 String prefix; 856 if (isElement && defaultNS != null && uri.equals(defaultNS)) { 857 prefix = ""; 858 } else { 859 prefix = nsSupport.getPrefix(uri); 860 } 861 if (prefix != null) { 862 return prefix; 863 } 864 prefix = (String ) doneDeclTable.get(uri); 865 if (prefix != null && 866 ((!isElement || defaultNS != null) && 867 "".equals(prefix) || nsSupport.getURI(prefix) != null)) { 868 prefix = null; 869 } 870 if (prefix == null) { 871 prefix = (String ) prefixTable.get(uri); 872 if (prefix != null && 873 ((!isElement || defaultNS != null) && 874 "".equals(prefix) || nsSupport.getURI(prefix) != null)) { 875 prefix = null; 876 } 877 } 878 if (prefix == null && qName != null && !"".equals(qName)) { 879 int i = qName.indexOf(':'); 880 if (i == -1) { 881 if (isElement && defaultNS == null) { 882 prefix = ""; 883 } 884 } else { 885 prefix = qName.substring(0, i); 886 } 887 } 888 for (; 889 prefix == null || nsSupport.getURI(prefix) != null; 890 prefix = "__NS" + ++prefixCounter) 891 ; 892 nsSupport.declarePrefix(prefix, uri); 893 doneDeclTable.put(uri, prefix); 894 return prefix; 895 } 896 897 898 909 private void write(char c) throws SAXException { 910 try { 911 output.write(c); 912 } 913 catch (IOException ex) { 914 throw new SAXException (ex); 915 } 916 } 917 918 919 930 private void write (String s) throws SAXException { 931 try { 932 output.write(s); 933 } 934 catch (IOException e) { 935 throw new SAXException (e); 936 } 937 } 938 939 940 955 private void writeAttributes (Attributes atts) 956 throws SAXException { 957 int len = atts.getLength(); 958 for (int i = 0; i < len; i++) { 959 char[] ch = atts.getValue(i).toCharArray(); 960 write(' '); 961 writeName(atts.getURI(i), atts.getLocalName(i), 962 atts.getQName(i), false); 963 write("=\""); 964 writeEsc(ch, 0, ch.length, true); 965 write('"'); 966 } 967 } 968 969 970 984 private void writeEsc (char[] ch, int start, int length, boolean isAttVal) 985 throws SAXException { 986 for (int i = start; i < start + length; i++) { 987 switch (ch[i]) { 988 case '&': 989 write("&"); 990 break; 991 case '<': 992 write("<"); 993 break; 994 case '>': 995 write(">"); 996 break; 997 case '\"': 998 if (isAttVal) { 999 write("""); 1000 } 1001 else { 1002 write('\"'); 1003 } 1004 break; 1005 default: 1006 if (ch[i] > '\u007f') { 1007 write("&#"); 1008 write(Integer.toString(ch[i])); 1009 write(';'); 1010 } 1011 else { 1012 write(ch[i]); 1013 } 1014 } 1015 } 1016 } 1017 1018 1031 private void write(char[] ch, int start, int length) 1032 throws SAXException { 1033 1034 try { 1035 output.write(ch, start, length); 1036 } 1037 catch (IOException e) { 1038 throw new SAXException (e); 1039 } 1040 1041 } 1042 1043 1044 1054 private void writeNSDecls() throws SAXException { 1055 Enumeration prefixes = nsSupport.getDeclaredPrefixes(); 1056 while (prefixes.hasMoreElements()) { 1057 String prefix = (String ) prefixes.nextElement(); 1058 String uri = nsSupport.getURI(prefix); 1059 if (uri == null) { 1060 uri = ""; 1061 } 1062 char[] ch = uri.toCharArray(); 1063 write(' '); 1064 if ("".equals(prefix)) { 1065 write("xmlns=\""); 1066 } 1067 else { 1068 write("xmlns:"); 1069 write(prefix); 1070 write("=\""); 1071 } 1072 writeEsc(ch, 0, ch.length, true); 1073 write('\"'); 1074 } 1075 } 1076 1077 1078 1094 private void writeName (String uri, String localName, 1095 String qualifiedName, boolean isElement) 1096 throws SAXException { 1097 String prefix = doPrefix(uri, qualifiedName, isElement); 1098 if (prefix != null && !"".equals(prefix)) { 1099 write(prefix); 1100 write(':'); 1101 } 1102 write(localName); 1103 } 1104 1105 1106 1107 1111 private final Attributes EMPTY_ATTS = new AttributesImpl (); 1112 1113 1114 1118 private Hashtable prefixTable; 1119 private Hashtable forcedDeclTable; 1120 private Hashtable doneDeclTable; 1121 private int elementLevel = 0; 1122 private Writer output; 1123 private NamespaceSupport nsSupport; 1124 private int prefixCounter = 0; 1125 1126 1127 1131 1132 public void endCDATA() {} 1133 1134 public void endDTD() throws SAXException { 1135 write(">"); 1136 } 1137 1138 public void startCDATA() {} 1139 1140 public void comment(char[] ch, int start, int length) 1141 throws SAXException { 1142 write("<!--"); 1143 write(ch, start, length); 1144 write("-->"); 1145 if (elementLevel < 1) { 1146 write('\n'); 1147 } 1148 } 1149 1150 public void endEntity(String name) {} 1151 public void startEntity(String name) {} 1152 1153 public void startDTD(String name, String publicID, String systemID) 1154 throws SAXException { 1155 write("<!DOCTYPE "); 1156 write(name); 1157 if (systemID != null) { 1158 if (publicID != null) { 1159 write(" PUBLIC \""); 1160 write(publicID); 1161 write("\" \""); 1162 write(systemID); 1163 write("\""); 1164 } 1165 else { 1166 write(" SYSTEM \""); 1167 write(systemID); 1168 write("\""); 1169 } 1170 } 1171 1172 } 1173 1174} 1175 1176 1178 | Popular Tags |