1 54 package sax; 55 56 import java.io.IOException ; 57 import java.io.OutputStreamWriter ; 58 import java.io.Writer ; 59 import java.util.Enumeration ; 60 import java.util.HashMap ; 61 import java.util.Iterator ; 62 import java.util.Map ; 63 64 import org.xml.sax.Attributes ; 65 import org.xml.sax.InputSource ; 66 import org.xml.sax.SAXException ; 67 import org.xml.sax.XMLReader ; 68 import org.xml.sax.helpers.NamespaceSupport ; 69 70 71 259 public class XMLWriter extends XMLFilterBase 260 { 261 262 263 267 268 273 public XMLWriter() 274 { 275 init(null); 276 } 277 278 279 287 public XMLWriter(Writer writer) 288 { 289 init(writer); 290 } 291 292 293 301 public XMLWriter(XMLReader xmlreader) 302 { 303 super(xmlreader); 304 init(null); 305 } 306 307 308 319 public XMLWriter(XMLReader xmlreader, Writer writer) 320 { 321 super(xmlreader); 322 init(writer); 323 } 324 325 326 334 private void init (Writer writer) 335 { 336 setOutput(writer); 337 nsSupport = new NamespaceSupport (); 338 prefixTable = new HashMap (); 339 forcedDeclTable = new HashMap (); 340 doneDeclTable = new HashMap (); 341 } 342 343 344 345 349 350 369 public void reset () 370 { 371 openElement = false; 372 elementLevel = 0; 373 prefixCounter = 0; 374 nsSupport.reset(); 375 inDTD = false; 376 } 377 378 379 393 public void flush () 394 throws IOException 395 { 396 output.flush(); 397 } 398 399 400 408 public void setOutput (Writer writer) 409 { 410 if (writer == null) { 411 output = new OutputStreamWriter (System.out); 412 } else { 413 output = writer; 414 } 415 } 416 417 418 432 public void setPrefix (String uri, String prefix) 433 { 434 prefixTable.put(uri, prefix); 435 } 436 437 438 445 public String getPrefix (String uri) 446 { 447 return (String )prefixTable.get(uri); 448 } 449 450 451 467 public void forceNSDecl (String uri) 468 { 469 forcedDeclTable.put(uri, Boolean.TRUE); 470 } 471 472 473 486 public void forceNSDecl (String uri, String prefix) 487 { 488 setPrefix(uri, prefix); 489 forceNSDecl(uri); 490 } 491 492 493 494 498 499 509 public void startDocument () 510 throws SAXException 511 { 512 reset(); 513 write("<?xml version=\"1.0\"?>\n\n"); 515 super.startDocument(); 516 } 517 518 519 529 public void endDocument () 530 throws SAXException 531 { 532 closeElement(); 533 write('\n'); 534 super.endDocument(); 535 try { 536 flush(); 537 } catch (IOException e) { 538 throw new SAXException (e); 539 } 540 } 541 542 543 562 public void startElement (String uri, String localName, 563 String qName, Attributes atts) 564 throws SAXException 565 { 566 closeElement(); 567 elementLevel++; 568 nsSupport.pushContext(); 569 write('<'); 570 writeName(uri, localName, qName, true); 571 writeAttributes(atts); 572 if (elementLevel == 1) { 573 forceNSDecls(); 574 } 575 writeNSDecls(); 576 openElement = true; 577 super.startElement(uri, localName, qName, atts); 578 } 579 580 581 599 public void endElement (String uri, String localName, String qName) 600 throws SAXException 601 { 602 if (openElement) { 603 write("/>"); 604 openElement = false; 605 } else { 606 write("</"); 607 writeName(uri, localName, qName, true); 608 write('>'); 609 } 610 if (elementLevel == 1) { 611 write('\n'); 612 } 613 super.endElement(uri, localName, qName); 614 nsSupport.popContext(); 615 elementLevel--; 616 } 617 618 619 632 public void characters (char ch[], int start, int len) 633 throws SAXException 634 { 635 closeElement(); 636 writeEsc(ch, start, len, false); 637 super.characters(ch, start, len); 638 } 639 640 641 654 public void ignorableWhitespace (char ch[], int start, int length) 655 throws SAXException 656 { 657 closeElement(); 658 writeEsc(ch, start, length, false); 659 super.ignorableWhitespace(ch, start, length); 660 } 661 662 663 664 676 public void processingInstruction (String target, String data) 677 throws SAXException 678 { 679 closeElement(); 680 write("<?"); 681 write(target); 682 write(' '); 683 write(data); 684 write("?>"); 685 if (elementLevel < 1) { 686 write('\n'); 687 } 688 super.processingInstruction(target, data); 689 } 690 691 692 693 697 698 712 public void startDTD(String name, String publicId, String systemId) 713 throws SAXException { 714 inDTD = true; 716 write("<!DOCTYPE "); 717 write(name); 718 boolean hasPublic = publicId != null && !publicId.equals(""); 719 if (hasPublic) { 720 write(" PUBLIC \""); 721 write(publicId); 722 write('\"'); 723 } 724 if (systemId != null && !systemId.equals("")) { 725 if (!hasPublic) { 726 write(" SYSTEM"); 727 } 728 write(" \""); 729 write(systemId); 730 write('\"'); 731 } 732 write(">\n\n"); 733 super.startDTD(name, publicId, systemId); 734 } 735 736 737 746 public void endDTD() 747 throws SAXException { 748 inDTD = false; 749 super.endDTD(); 750 } 751 752 753 765 public void startEntity(String name) 766 throws SAXException { 767 closeElement(); 768 write('&'); 769 write(name); 770 write(';'); 771 super.startEntity(name); 772 } 773 774 775 785 public void endEntity(String name) 786 throws SAXException { 787 super.endEntity(name); 788 } 789 790 791 800 public void startCDATA() 801 throws SAXException { 802 closeElement(); 803 write("<![CDATA["); 804 super.startCDATA(); 805 } 806 807 808 817 public void endCDATA() 818 throws SAXException { 819 write("]]>"); 820 super.endCDATA(); 821 } 822 823 824 836 public void comment(char[] ch, int start, int length) 837 throws SAXException { 838 if (!inDTD) { 839 closeElement(); 840 write("<!--"); 841 write(ch, start, length); 842 write("-->"); 843 if (elementLevel < 1) { 844 write('\n'); 845 } 846 } 847 super.comment(ch, start, length); 848 } 849 850 851 852 856 857 863 private void forceNSDecls () 864 { 865 Iterator prefixes = forcedDeclTable.keySet().iterator(); 866 while (prefixes.hasNext()) { 867 String prefix = (String )prefixes.next(); 868 doPrefix(prefix, null, true); 869 } 870 } 871 872 873 886 private String doPrefix (String uri, String qName, boolean isElement) 887 { 888 String defaultNS = nsSupport.getURI(""); 889 if ("".equals(uri)) { 890 if (isElement && defaultNS != null) 891 nsSupport.declarePrefix("", ""); 892 return null; 893 } 894 String prefix; 895 if (isElement && defaultNS != null && uri.equals(defaultNS)) { 896 prefix = ""; 897 } else { 898 prefix = nsSupport.getPrefix(uri); 899 } 900 if (prefix != null) { 901 return prefix; 902 } 903 prefix = (String ) doneDeclTable.get(uri); 904 if (prefix != null && 905 ((!isElement || defaultNS != null) && 906 "".equals(prefix) || nsSupport.getURI(prefix) != null)) { 907 prefix = null; 908 } 909 if (prefix == null) { 910 prefix = (String ) prefixTable.get(uri); 911 if (prefix != null && 912 ((!isElement || defaultNS != null) && 913 "".equals(prefix) || nsSupport.getURI(prefix) != null)) { 914 prefix = null; 915 } 916 } 917 if (prefix == null && qName != null && !"".equals(qName)) { 918 int i = qName.indexOf(':'); 919 if (i == -1) { 920 if (isElement && defaultNS == null) { 921 prefix = ""; 922 } 923 } else { 924 prefix = qName.substring(0, i); 925 } 926 } 927 for (; 928 prefix == null || nsSupport.getURI(prefix) != null; 929 prefix = "__NS" + ++prefixCounter) 930 ; 931 nsSupport.declarePrefix(prefix, uri); 932 doneDeclTable.put(uri, prefix); 933 return prefix; 934 } 935 936 937 945 private void write (char c) 946 throws SAXException 947 { 948 try { 949 output.write(c); 950 } catch (IOException e) { 951 throw new SAXException (e); 952 } 953 } 954 955 956 966 private void write (char[] cbuf, int off, int len) 967 throws SAXException 968 { 969 try { 970 output.write(cbuf, off, len); 971 } catch (IOException e) { 972 throw new SAXException (e); 973 } 974 } 975 976 977 985 private void write (String s) 986 throws SAXException 987 { 988 try { 989 output.write(s); 990 } catch (IOException e) { 991 throw new SAXException (e); 992 } 993 } 994 995 996 1006 private void writeAttributes (Attributes atts) 1007 throws SAXException 1008 { 1009 int len = atts.getLength(); 1010 for (int i = 0; i < len; i++) { 1011 char ch[] = atts.getValue(i).toCharArray(); 1012 write(' '); 1013 writeName(atts.getURI(i), atts.getLocalName(i), 1014 atts.getQName(i), false); 1015 write("=\""); 1016 writeEsc(ch, 0, ch.length, true); 1017 write('"'); 1018 } 1019 } 1020 1021 1022 1033 private void writeEsc (char ch[], int start, 1034 int length, boolean isAttVal) 1035 throws SAXException 1036 { 1037 for (int i = start; i < start + length; i++) { 1038 switch (ch[i]) { 1039 case '&': 1040 write("&"); 1041 break; 1042 case '<': 1043 write("<"); 1044 break; 1045 case '>': 1046 write(">"); 1047 break; 1048 case '\"': 1049 if (isAttVal) { 1050 write("""); 1051 } else { 1052 write('\"'); 1053 } 1054 break; 1055 default: 1056 if (ch[i] > '\u007f') { 1057 write("&#"); 1058 write(Integer.toString(ch[i])); 1059 write(';'); 1060 } else { 1061 write(ch[i]); 1062 } 1063 } 1064 } 1065 } 1066 1067 1068 1076 private void writeNSDecls () 1077 throws SAXException 1078 { 1079 Enumeration prefixes = nsSupport.getDeclaredPrefixes(); 1080 while (prefixes.hasMoreElements()) { 1081 String prefix = (String ) prefixes.nextElement(); 1082 String uri = nsSupport.getURI(prefix); 1083 if (uri == null) { 1084 uri = ""; 1085 } 1086 char ch[] = uri.toCharArray(); 1087 write(' '); 1088 if ("".equals(prefix)) { 1089 write("xmlns=\""); 1090 } else { 1091 write("xmlns:"); 1092 write(prefix); 1093 write("=\""); 1094 } 1095 writeEsc(ch, 0, ch.length, true); 1096 write('\"'); 1097 } 1098 } 1099 1100 1101 1113 private void writeName (String uri, String localName, 1114 String qName, boolean isElement) 1115 throws SAXException 1116 { 1117 String prefix = doPrefix(uri, qName, isElement); 1118 if (prefix != null && !"".equals(prefix)) { 1119 write(prefix); 1120 write(':'); 1121 } 1122 write(localName); 1123 } 1124 1125 1126 1129 private void closeElement() 1130 throws SAXException 1131 { 1132 if (openElement) { 1133 write('>'); 1134 openElement = false; 1135 } 1136 } 1137 1138 1139 1140 1144 private Map prefixTable; 1145 private Map forcedDeclTable; 1146 private Map doneDeclTable; 1147 private boolean openElement = false; 1148 private int elementLevel = 0; 1149 private Writer output; 1150 private NamespaceSupport nsSupport; 1151 private int prefixCounter = 0; 1152 private boolean inDTD = false; 1153 1154} 1155 1156 | Popular Tags |