[jdom-interest] AleXMLOutputter

Alex Chaffee guru at edamame.stinky.com
Fri Jul 14 07:45:17 PDT 2000


While Rusty is busy refactoring XMLOutputter in order to cleanly deal
with encoding issues, I've gone ahead and solved the encoding issues
by ignoring them. :-)

I rewrote XMLOutputter to have public methods for serializing nodes
other than document.  Patch is at the end of this email.  I don't want
to step on Rusty's toes here, but the fact is, my code works, more or
less, so an argument could be made for checking it into the main code
base pending further developments from Rusty's camp.


Changes:

- changed name to AlexOutputter (this should be changed back ;-)

- added preserveWhitespace property; output methods pass this to
getContent and getMixedContent when fetching strings

- added methods setIndent, setNewlines, setPreserveWhitespace,
setEncoding, setLineSeparator

- made newline property rather than static (so it can be set)

- methods printComment, printProcessingInstruction, printDeclaration,
printDocType, printElement, printEntity, printNamespace,
printAttributes are now public

To do:

- add method signatures for most print* methods that don't require
"indent" parameter (default to 0, like printElement does already)


-- 
Alex Chaffee                       mailto:alex at jguru.com
jGuru - Java News and FAQs         http://www.jguru.com/alex/
Creator of Gamelan                 http://www.gamelan.com/
Founder of Purple Technology       http://www.purpletech.com/
Curator of Stinky Art Collective   http://www.stinky.com/



--- d:/jdom-dev/jdom/src/java/org/jdom/output/XMLOutputter.java	Thu Jul 13 02:33:06 2000
+++ src/AlexOutputter.java	Fri Jul 14 14:11:58 2000
@@ -39,8 +39,6 @@
  Project, please see <http://www.jdom.org/>.
 
  */
-package org.jdom.output;
-
 import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -62,7 +60,7 @@
 import org.jdom.ProcessingInstruction;
 
 /**
- * <p><code>XMLOutputter</code> takes a JDOM tree and
+ * <p><code>AlexOutputter</code> takes a JDOM tree and
  *   formats it to a stream as XML.  This formatter performs typical
  *   document formatting.  The XML declaration
  *   and processing instructions are always on their own lines.  Empty
@@ -80,7 +78,7 @@
  * @author Elliotte Rusty Harold
  * @version 1.0
  */
-public class XMLOutputter {
+public class AlexOutputter {
 
     /** The default indent, two spaces */
     private String indent = "  ";
@@ -88,6 +86,9 @@
     /** The default new line flag, set to do new lines */
     private boolean newlines = true;
 
+    /** should  getContent() preserve whitespace or not? */
+    private boolean preserveWhitespace = true;
+
     /** The encoding format */
     private String enc = "UTF8";
 
@@ -96,30 +97,30 @@
 
     /**
      * <p>
-     * This will create an <code>XMLOutputter</code> with
+     * This will create an <code>AlexOutputter</code> with
      *   a two-space indent and new lines on.
      * </p>
      */
-    public XMLOutputter() {
+    public AlexOutputter() {
         namespaces = new LinkedList();
     }
 
     /**
      * <p>
-     * This will create an <code>XMLOutputter</code> with
+     * This will create an <code>AlexOutputter</code> with
      *   the given indent and new lines on.
      * </p>
      *
      * @param indent  the indent string, usually some number of spaces
      */
-    public XMLOutputter(String indent) {
+    public AlexOutputter(String indent) {
        this.indent = indent;
        namespaces = new LinkedList();
     }
 
     /**
      * <p>
-     * This will create an <code>XMLOutputter</code> with
+     * This will create an <code>AlexOutputter</code> with
      *   the given indent that prints newlines only if <code>newlines</code> is
      *   <code>true</code>.
      * </p>
@@ -129,7 +130,7 @@
      * @param newlines <code>true</code> indicates new lines should be
      *                 printed, else new lines are ignored (compacted).
      */
-    public XMLOutputter(String indent, boolean newlines) {
+    public AlexOutputter(String indent, boolean newlines) {
        this.indent = indent;
        this.newlines = newlines;
        namespaces = new LinkedList();
@@ -137,7 +138,7 @@
 
     /**
      * <p>
-     * This will create an <code>XMLOutputter</code> with
+     * This will create an <code>AlexOutputter</code> with
      *   the given indent and new lines printing only if newlines is
      *   <code>true</code>, and encoding format <code>encoding</code>.
      * </p>
@@ -148,13 +149,34 @@
      *                 printed, else new lines are ignored (compacted).
      * @param encoding set encoding format.
      */
-    public XMLOutputter(String indent, boolean newlines, String encoding) {
+    public AlexOutputter(String indent, boolean newlines, String encoding) {
        this.indent = indent;
        this.newlines = newlines;
        this.enc = encoding;
        namespaces = new LinkedList();
     }
 
+    public void setIndent(String indent) {
+	this.indent = indent;
+    }
+    
+    public void setNewlines(boolean newlines) {
+	this.newlines = newlines;
+    }
+
+    public void setPreserveWhitespace(boolean preserveWhitespace) {
+	this.preserveWhitespace = preserveWhitespace;
+    }
+
+    public void setEncoding(String encoding) {
+	this.enc = encoding;
+    }
+    
+    public void setLineSeparator(String newline) {
+	this.newline = newline;
+    }
+    
+    
     /**
      * <p>
      * This will print the proper indent characters for the given indent level.
@@ -177,7 +199,7 @@
     // solution. However both carriage return and linefeed are
     // required for many network protocols, and the parser on the
     // other end should normalize this. 
-    private static String newline = "\r\n";
+    private String newline = "\r\n";
 
     /**
      * <p>
@@ -217,6 +239,7 @@
         // Print out root element, as well as any root level
         // comments and processing instructions, 
         // starting with no indentation
+	// XXX needs to say doc.getMixedContent(preserveWhitespace) as soon as available
         Iterator i = doc.getMixedContent().iterator();
         while (i.hasNext()) {
             Object obj = i.next();
@@ -259,7 +282,7 @@
      * @param out <code>Writer</code> to write to.
      * @param indentLevel Current depth in hierarchy.
      */
-    protected void printComment(Comment comment,
+    public void printComment(Comment comment,
                                     Writer out, int indentLevel) throws IOException {
                                         
         indent(out, indentLevel);
@@ -277,7 +300,7 @@
      * @param out <code>Writer</code> to write to.
      * @param indentLevel Current depth in hierarchy.
      */
-    protected void printProcessingInstruction(ProcessingInstruction pi,
+    public void printProcessingInstruction(ProcessingInstruction pi,
                                     Writer out, int indentLevel) throws IOException {
                                         
         indent(out, indentLevel);
@@ -296,7 +319,7 @@
      * @param docType <code>DocType</code> whose declaration to write.
      * @param out <code>Writer</code> to write to.
      */
-    protected void printDeclaration(Document doc,
+    public void printDeclaration(Document doc,
                                     Writer out,
                                     String encoding)  throws IOException {
         // Assume 1.0 version
@@ -318,7 +341,7 @@
      * @param doc <code>Document</code> whose declaration to write.
      * @param out <code>Writer</code> to write to.
      */
-    protected void printDocType(DocType docType, Writer out)  throws IOException {
+    public void printDocType(DocType docType, Writer out)  throws IOException {
         if (docType == null) {
             return;
         }
@@ -355,17 +378,31 @@
      *
      * @param element <code>Element</code> to output.
      * @param out <code>Writer</code> to write to.
+     */
+    public void printElement(Element element, Writer out)
+	throws IOException
+    {
+	printElement(element, out, 0);
+    }
+
+    /**
+     * <p>
+     * This will handle printing out an <code>{@link Element}</code>,
+     *   its <code>{@link Attribute}</code>s, and its value.
+     * </p>
+     *
+     * @param element <code>Element</code> to output.
+     * @param out <code>Writer</code> to write to.
      * @param indent <code>int</code> level of indention.
      */
     protected void printElement(Element element, Writer out,
                                 int indentLevel)  throws IOException {
 
-        List mixedContent = element.getMixedContent();
-
+        List mixedContent = element.getMixedContent(preserveWhitespace);
         boolean empty = mixedContent.size() == 0;
         boolean stringOnly =
             !empty &&
-            mixedContent.size() == 1 &&
+            (mixedContent.size() == 1) &&
             mixedContent.get(0) instanceof String;
 
         // Print beginning element tag
@@ -394,15 +431,59 @@
             // Simply close up
             out.write(" />");
             maybePrintln(out);
-        } else if (stringOnly) {
-            // Print the tag  with String on same line
-            // Example: <tag name="value">content</tag>
+        } else {
             out.write(">");
-            out.write(escapeElementEntities(element.getContent()));
+	    if (!stringOnly)
+		maybePrintln(out);		
+	    printElementContent(element, out, indentLevel);	    
+            indent(out, indentLevel);
             out.write("</");
             out.write(element.getQualifiedName());
             out.write(">");
             maybePrintln(out);
+
+           // After recursion, remove the namespace defined on the element (if any)
+           if (printedNS) {
+              namespaces.removeLast();
+           }
+	}
+    }
+    
+    /**
+     * <p> This will handle printing out an <code>{@link
+     * Element}</code>'s content only, not including its tag,
+     * attributes, and namespace info.  </p>
+     *
+     * @param element <code>Element</code> to output.
+     * @param out <code>Writer</code> to write to.
+     * @param indent <code>int</code> level of indention.  */
+    public void printElementContent(Element element, Writer out)
+	throws IOException
+    {
+	printElementContent(element, out, 0);
+    }
+
+/**
+     * <p> This will handle printing out an <code>{@link
+     * Element}</code>'s content only, not including its tag,
+     * attributes, and namespace info.  </p>
+     *
+     * @param element <code>Element</code> to output.
+     * @param out <code>Writer</code> to write to.
+     * @param indent <code>int</code> level of indention.  */
+    public void printElementContent(Element element, Writer out,
+                                int indentLevel)  throws IOException
+    {
+        List mixedContent = element.getMixedContent(preserveWhitespace);
+        boolean empty = mixedContent.size() == 0;
+        boolean stringOnly =
+            !empty &&
+            (mixedContent.size() == 1) &&
+            mixedContent.get(0) instanceof String;
+	if (stringOnly) {
+            // Print the tag  with String on same line
+            // Example: <tag name="value">content</tag>
+            out.write(escapeElementEntities(element.getContent(preserveWhitespace)));
         } else {
             /**
              * Print with children on future lines
@@ -411,8 +492,6 @@
              *             <child/>
              *          </tag>
              */
-            out.write(">");
-            maybePrintln(out);
             // Iterate through children
             Object content = null;
             for (int i=0, size=mixedContent.size(); i<size; i++) {
@@ -431,16 +510,6 @@
                 } // Unsupported types are *not* printed
             }
 
-            indent(out, indentLevel);
-            out.write("</");
-            out.write(element.getQualifiedName());
-            out.write(">");
-            maybePrintln(out);
-
-           // After recursion, remove the namespace defined on the element (if any)
-           if (printedNS) {
-              namespaces.removeLast();
-           }
         }
     }
     
@@ -455,7 +524,7 @@
      * @param entity <code>Entity</code> to output.
      * @param out <code>Writer</code> to write to.
      */
-    protected void printEntity(Entity entity, Writer out) throws IOException {
+    public void printEntity(Entity entity, Writer out) throws IOException {
         out.write(entity.getSerializedForm());
     }
     
@@ -469,7 +538,7 @@
      * @param ns <code>Namespace</code> to print definition of
      * @param out <code>Writer</code> to write to.
      */
-    protected void printNamespace(Namespace ns, Writer out) throws IOException {
+    public void printNamespace(Namespace ns, Writer out) throws IOException {
         out.write(" xmlns");
         if (!ns.getPrefix().equals("")) {
             out.write(":");
@@ -488,7 +557,7 @@
      * @param attributes <code>List</code> of Attribute objcts
      * @param out <code>Writer</code> to write to
      */
-    protected void printAttributes(List attributes, Writer out) throws IOException {
+    public void printAttributes(List attributes, Writer out) throws IOException {
         for (int i=0, size=attributes.size(); i<size; i++) {
             Attribute attribute = (Attribute)attributes.get(i);
             Namespace ns = attribute.getNamespace();




More information about the jdom-interest mailing list