| 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
|