| 1 56 57 package org.jdom.output; 58 59 import java.io.*; 60 import java.util.*; 61 62 import javax.xml.transform.Result ; 63 64 import org.jdom.*; 65 66 114 115 public class XMLOutputter implements Cloneable { 116 117 private static final String CVS_ID = 118 "@(#) $RCSfile: XMLOutputter.java,v $ $Revision: 1.113 $ $Date: 2004/12/11 01:31:50 $ $Name: $"; 119 120 private Format userFormat = Format.getRawFormat(); 122 123 protected static final Format preserveFormat = Format.getRawFormat(); 125 126 protected Format currentFormat = userFormat; 128 129 131 private boolean escapeOutput = true; 132 133 136 140 public XMLOutputter() { 141 } 142 143 148 public XMLOutputter(Format format) { 149 userFormat = (Format) format.clone(); 150 currentFormat = userFormat; 151 } 152 153 161 public XMLOutputter(XMLOutputter that) { 162 this.userFormat = (Format) that.userFormat.clone(); 163 currentFormat = userFormat; 164 } 165 166 169 175 public void setFormat(Format newFormat) { 176 this.userFormat = (Format) newFormat.clone(); 177 this.currentFormat = userFormat; 178 } 179 180 184 public Format getFormat() { 185 return (Format) userFormat.clone(); 186 } 187 188 191 200 public void output(Document doc, OutputStream out) 201 throws IOException { 202 Writer writer = makeWriter(out); 203 output(doc, writer); } 205 206 212 public void output(DocType doctype, OutputStream out) throws IOException { 213 Writer writer = makeWriter(out); 214 output(doctype, writer); } 216 217 225 public void output(Element element, OutputStream out) throws IOException { 226 Writer writer = makeWriter(out); 227 output(element, writer); } 229 230 240 public void outputElementContent(Element element, OutputStream out) 241 throws IOException { 242 Writer writer = makeWriter(out); 243 outputElementContent(element, writer); } 245 246 255 public void output(List list, OutputStream out) 256 throws IOException { 257 Writer writer = makeWriter(out); 258 output(list, writer); } 260 261 267 public void output(CDATA cdata, OutputStream out) throws IOException { 268 Writer writer = makeWriter(out); 269 output(cdata, writer); } 271 272 279 public void output(Text text, OutputStream out) throws IOException { 280 Writer writer = makeWriter(out); 281 output(text, writer); } 283 284 290 public void output(Comment comment, OutputStream out) throws IOException { 291 Writer writer = makeWriter(out); 292 output(comment, writer); } 294 295 301 public void output(ProcessingInstruction pi, OutputStream out) 302 throws IOException { 303 Writer writer = makeWriter(out); 304 output(pi, writer); } 306 307 313 public void output(EntityRef entity, OutputStream out) throws IOException { 314 Writer writer = makeWriter(out); 315 output(entity, writer); } 317 318 322 private Writer makeWriter(OutputStream out) 323 throws java.io.UnsupportedEncodingException { 324 return makeWriter(out, userFormat.encoding); 325 } 326 327 330 private static Writer makeWriter(OutputStream out, String enc) 331 throws java.io.UnsupportedEncodingException { 332 if ("UTF-8".equals(enc)) { 335 enc = "UTF8"; 336 } 337 338 Writer writer = new BufferedWriter( 339 (new OutputStreamWriter( 340 new BufferedOutputStream(out), enc) 341 )); 342 return writer; 343 } 344 345 348 362 public void output(Document doc, Writer out) throws IOException { 363 364 printDeclaration(out, doc, userFormat.encoding); 365 366 List content = doc.getContent(); 370 int size = content.size(); 371 for (int i = 0; i < size; i++) { 372 Object obj = content.get(i); 373 374 if (obj instanceof Element) { 375 printElement(out, doc.getRootElement(), 0, 376 createNamespaceStack()); 377 } 378 else if (obj instanceof Comment) { 379 printComment(out, (Comment) obj); 380 } 381 else if (obj instanceof ProcessingInstruction) { 382 printProcessingInstruction(out, (ProcessingInstruction) obj); 383 } 384 else if (obj instanceof DocType) { 385 printDocType(out, doc.getDocType()); 386 out.write(currentFormat.lineSeparator); 389 } 390 else { 391 } 394 395 newline(out); 396 indent(out, 0); 397 } 398 399 out.write(currentFormat.lineSeparator); 402 403 out.flush(); 404 } 405 406 412 public void output(DocType doctype, Writer out) throws IOException { 413 printDocType(out, doctype); 414 out.flush(); 415 } 416 417 425 public void output(Element element, Writer out) throws IOException { 426 printElement(out, element, 0, createNamespaceStack()); 429 out.flush(); 430 } 431 432 442 public void outputElementContent(Element element, Writer out) 443 throws IOException { 444 List content = element.getContent(); 445 printContentRange(out, content, 0, content.size(), 446 0, createNamespaceStack()); 447 out.flush(); 448 } 449 450 459 public void output(List list, Writer out) 460 throws IOException { 461 printContentRange(out, list, 0, list.size(), 462 0, createNamespaceStack()); 463 out.flush(); 464 } 465 466 472 public void output(CDATA cdata, Writer out) throws IOException { 473 printCDATA(out, cdata); 474 out.flush(); 475 } 476 477 484 public void output(Text text, Writer out) throws IOException { 485 printText(out, text); 486 out.flush(); 487 } 488 489 495 public void output(Comment comment, Writer out) throws IOException { 496 printComment(out, comment); 497 out.flush(); 498 } 499 500 506 public void output(ProcessingInstruction pi, Writer out) 507 throws IOException { 508 boolean currentEscapingPolicy = currentFormat.ignoreTrAXEscapingPIs; 509 510 currentFormat.setIgnoreTrAXEscapingPIs(true); 512 printProcessingInstruction(out, pi); 513 currentFormat.setIgnoreTrAXEscapingPIs(currentEscapingPolicy); 514 515 out.flush(); 516 } 517 518 524 public void output(EntityRef entity, Writer out) throws IOException { 525 printEntityRef(out, entity); 526 out.flush(); 527 } 528 529 532 539 public String outputString(Document doc) { 540 StringWriter out = new StringWriter(); 541 try { 542 output(doc, out); } catch (IOException e) { } 544 return out.toString(); 545 } 546 547 554 public String outputString(DocType doctype) { 555 StringWriter out = new StringWriter(); 556 try { 557 output(doctype, out); } catch (IOException e) { } 559 return out.toString(); 560 } 561 562 569 public String outputString(Element element) { 570 StringWriter out = new StringWriter(); 571 try { 572 output(element, out); } catch (IOException e) { } 574 return out.toString(); 575 } 576 577 583 public String outputString(List list) { 584 StringWriter out = new StringWriter(); 585 try { 586 output(list, out); } catch (IOException e) { } 588 return out.toString(); 589 } 590 591 598 public String outputString(CDATA cdata) { 599 StringWriter out = new StringWriter(); 600 try { 601 output(cdata, out); } catch (IOException e) { } 603 return out.toString(); 604 } 605 606 613 public String outputString(Text text) { 614 StringWriter out = new StringWriter(); 615 try { 616 output(text, out); } catch (IOException e) { } 618 return out.toString(); 619 } 620 621 622 629 public String outputString(Comment comment) { 630 StringWriter out = new StringWriter(); 631 try { 632 output(comment, out); } catch (IOException e) { } 634 return out.toString(); 635 } 636 637 644 public String outputString(ProcessingInstruction pi) { 645 StringWriter out = new StringWriter(); 646 try { 647 output(pi, out); } catch (IOException e) { } 649 return out.toString(); 650 } 651 652 659 public String outputString(EntityRef entity) { 660 StringWriter out = new StringWriter(); 661 try { 662 output(entity, out); } catch (IOException e) { } 664 return out.toString(); 665 } 666 667 670 678 protected void printDeclaration(Writer out, Document doc, 679 String encoding) throws IOException { 680 681 if (!userFormat.omitDeclaration) { 683 out.write("<?xml version=\"1.0\""); 685 if (!userFormat.omitEncoding) { 686 out.write(" encoding=\"" + encoding + "\""); 687 } 688 out.write("?>"); 689 690 out.write(currentFormat.lineSeparator); 694 } 695 } 696 697 703 protected void printDocType(Writer out, DocType docType) 704 throws IOException { 705 706 String publicID = docType.getPublicID(); 707 String systemID = docType.getSystemID(); 708 String internalSubset = docType.getInternalSubset(); 709 boolean hasPublic = false; 710 711 out.write("<!DOCTYPE "); 712 out.write(docType.getElementName()); 713 if (publicID != null) { 714 out.write(" PUBLIC \""); 715 out.write(publicID); 716 out.write("\""); 717 hasPublic = true; 718 } 719 if (systemID != null) { 720 if (!hasPublic) { 721 out.write(" SYSTEM"); 722 } 723 out.write(" \""); 724 out.write(systemID); 725 out.write("\""); 726 } 727 if ((internalSubset != null) && (!internalSubset.equals(""))) { 728 out.write(" ["); 729 out.write(currentFormat.lineSeparator); 730 out.write(docType.getInternalSubset()); 731 out.write("]"); 732 } 733 out.write(">"); 734 } 735 736 742 protected void printComment(Writer out, Comment comment) 743 throws IOException { 744 out.write("<!--"); 745 out.write(comment.getText()); 746 out.write("-->"); 747 } 748 749 755 protected void printProcessingInstruction(Writer out, ProcessingInstruction pi 756 ) throws IOException { 757 String target = pi.getTarget(); 758 boolean piProcessed = false; 759 760 if (currentFormat.ignoreTrAXEscapingPIs == false) { 761 if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING)) { 762 escapeOutput = false; 763 piProcessed = true; 764 } 765 else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING)) { 766 escapeOutput = true; 767 piProcessed = true; 768 } 769 } 770 if (piProcessed == false) { 771 String rawData = pi.getData(); 772 773 if (!"".equals(rawData)) { 775 out.write("<?"); 776 out.write(target); 777 out.write(" "); 778 out.write(rawData); 779 out.write("?>"); 780 } 781 else { 782 out.write("<?"); 783 out.write(target); 784 out.write("?>"); 785 } 786 } 787 } 788 789 797 protected void printEntityRef(Writer out, EntityRef entity) 798 throws IOException { 799 out.write("&"); 800 out.write(entity.getName()); 801 out.write(";"); 802 } 803 804 810 protected void printCDATA(Writer out, CDATA cdata) throws IOException { 811 String str = (currentFormat.mode == Format.TextMode.NORMALIZE) 812 ? cdata.getTextNormalize() 813 : ((currentFormat.mode == Format.TextMode.TRIM) ? 814 cdata.getText().trim() : cdata.getText()); 815 out.write("<![CDATA["); 816 out.write(str); 817 out.write("]]>"); 818 } 819 820 826 protected void printText(Writer out, Text text) throws IOException { 827 String str = (currentFormat.mode == Format.TextMode.NORMALIZE) 828 ? text.getTextNormalize() 829 : ((currentFormat.mode == Format.TextMode.TRIM) ? 830 text.getText().trim() : text.getText()); 831 out.write(escapeElementEntities(str)); 832 } 833 834 838 private void printString(Writer out, String str) throws IOException { 839 if (currentFormat.mode == Format.TextMode.NORMALIZE) { 840 str = Text.normalizeString(str); 841 } 842 else if (currentFormat.mode == Format.TextMode.TRIM) { 843 str = str.trim(); 844 } 845 out.write(escapeElementEntities(str)); 846 } 847 848 858 protected void printElement(Writer out, Element element, 859 int level, NamespaceStack namespaces) 860 throws IOException { 861 862 List attributes = element.getAttributes(); 863 List content = element.getContent(); 864 865 String space = null; 867 if (attributes != null) { 868 space = element.getAttributeValue("space", 869 Namespace.XML_NAMESPACE); 870 } 871 872 Format previousFormat = currentFormat; 873 874 if ("default".equals(space)) { 875 currentFormat = userFormat; 876 } 877 else if ("preserve".equals(space)) { 878 currentFormat = preserveFormat; 879 } 880 881 out.write("<"); 884 printQualifiedName(out, element); 885 886 int previouslyDeclaredNamespaces = namespaces.size(); 888 889 printElementNamespace(out, element, namespaces); 891 892 printAdditionalNamespaces(out, element, namespaces); 894 895 if (attributes != null) 897 printAttributes(out, attributes, element, namespaces); 898 899 904 int start = skipLeadingWhite(content, 0); 905 int size = content.size(); 906 if (start >= size) { 907 if (currentFormat.expandEmptyElements) { 909 out.write("></"); 910 printQualifiedName(out, element); 911 out.write(">"); 912 } 913 else { 914 out.write(" />"); 915 } 916 } 917 else { 918 out.write(">"); 919 920 924 if (nextNonText(content, start) < size) { 925 newline(out); 927 printContentRange(out, content, start, size, 928 level + 1, namespaces); 929 newline(out); 930 indent(out, level); 931 } 932 else { 933 printTextRange(out, content, start, size); 935 } 936 out.write("</"); 937 printQualifiedName(out, element); 938 out.write(">"); 939 } 940 941 while (namespaces.size() > previouslyDeclaredNamespaces) { 943 namespaces.pop(); 944 } 945 946 currentFormat = previousFormat; 948 } 949 950 963 private void printContentRange(Writer out, List content, 964 int start, int end, int level, 965 NamespaceStack namespaces) 966 throws IOException { 967 boolean firstNode; Object next; int first, index; 971 index = start; 972 while (index < end) { 973 firstNode = (index == start) ? true : false; 974 next = content.get(index); 975 976 if ((next instanceof Text) || (next instanceof EntityRef)) { 980 first = skipLeadingWhite(content, index); 981 index = nextNonText(content, first); 98
|