[jdom-interest] PATCH: XMLOutputter refactoring/opening
Alex Chaffee
guru at edamame.stinky.com
Fri Sep 29 06:28:01 PDT 2000
I've patched XMLOutputter to make the following changes. Please
integrate these into the version in the repository.
Added trimText property: will set whether the text is output verbatim
(false) or with whitespace stripped as per Element.getTextTrim().
Default: false
Updated documentation slightly
Made methods to print the inside of documents public, to wit:
printComment
printProcessingInstruction
printDeclaration
printDocType
printCDATASection
printElement
Made clean convenience wrappers for a few of the above; the rest take
indent parameters (which can be 0).
Refactored printElement so it calls printElementContent; slighly
cleaner if-then-else logic.
Made printElementContent public, in case you want to print just the
content of an element, and not the open/close tags. (Believe it or
not, I had a need for this: printing an element whose content is an
HTML snippet, which could be mixed/nested content.)
Needs a bit of testing, esp. with namespaces (I'm no good at namespaces).
[Note: the setIndenting method seems redundant with setIndent(null) or
setIndent("") -- let's remove it?]
----------------
bash.exe-2.02$ cvs diff -u src/java/org/jdom/output/XMLOutputter.java
Index: src/java/org/jdom/output/XMLOutputter.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/output/XMLOutputter.java,v
retrieving revision 1.21
diff -u -r1.21 XMLOutputter.java
--- src/java/org/jdom/output/XMLOutputter.java 2000/09/20 00:30:40 1.21
+++ src/java/org/jdom/output/XMLOutputter.java 2000/09/29 13:41:21
@@ -97,6 +97,7 @@
* @author Elliotte Rusty Harold
* @author David & Will (from Post Tool Design)
* @author Dan Schaffer
+ * @author Alex Chaffee (alex at jguru.com)
* @version 1.0
*/
public class XMLOutputter {
@@ -125,6 +126,9 @@
/** New line separator */
private String newline = "\r\n";
+ /** should we preserve whitespace or not? */
+ private boolean trimText = false;
+
/**
* <p>
* This will create an <code>XMLOutputter</code> with
@@ -189,6 +193,16 @@
* <p>
* This will set the new-line separator. The default is <code>\r\n</code>.
* </p>
+ * <blockquote>
+ * We could change this to the System default,
+ * but I prefer not to make output platform dependent.
+ * A carriage return, linefeed pair is the most generally
+ * acceptable linebreak. Another possibility is to use
+ * only a line feed, which is XML's preferred (but not required)
+ * solution. However both carriage return and linefeed are
+ * required for many network protocols, and the parser on the
+ * other end should normalize this. --Rusty
+ * </blockquote>
*
* @param separator <code>String</code> line separator to use.
*/
@@ -239,6 +253,17 @@
/**
* <p>
+ * This will set whether the text is output verbatim (false) or with whitespace stripped as per Element.getTextTrim(). Default: false;
+ * </p>
+ *
+ * @param trimText <code>boolean</code> true=>trim the whitespace, false=>use text verbatim
+ */
+ public void setTrimText(boolean trimText) {
+ this.trimText = trimText;
+ }
+
+ /**
+ * <p>
* This will set the indent <code>String</code> to use; this is usually
* a <code>String</code> of empty spaces. Note that this will not affect the
* output if no indentation is being used. This can be set through
@@ -381,7 +406,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);
@@ -399,7 +424,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);
@@ -418,7 +443,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 {
@@ -452,7 +477,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;
}
@@ -491,7 +516,7 @@
* @param out <code>Writer</code> to write to.
* @param indent <code>int</code> level of indention.
*/
- protected void printCDATASection(CDATA cdata,
+ public void printCDATASection(CDATA cdata,
Writer out, int indentLevel) throws IOException {
indent(out, indentLevel);
@@ -503,14 +528,31 @@
/**
* <p>
* This will handle printing out an <code>{@link Element}</code>,
- * its <code>{@link Attribute}</code>s, and its value.
+ * its <code>{@link Attribute}</code>s, and its value, and all
+ * contained (child) elements etc.
+ * </p>
+ *
+ * @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, and all
+ * contained (child) elements etc.
* </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,
+ public void printElement(Element element, Writer out,
int indentLevel) throws IOException {
// if this is the root element we could pre-initialize the namespace stack
@@ -565,6 +607,16 @@
printAttributes(element.getAttributes(), element, out, namespaces);
+ // handle "" string same as empty
+ if (stringOnly) {
+ String elementText =
+ trimText ? element.getTextTrim() : element.getText();
+ if (elementText == null ||
+ elementText.equals("")) {
+ empty = true;
+ }
+ }
+
if (empty) {
// Simply close up
if (!expandEmptyElements) {
@@ -574,28 +626,79 @@
out.write(element.getQualifiedName());
out.write(">");
}
+ maybePrintln(out);
+ } else {
+ // we know it's not null or empty from above
+ out.write(">");
+
+ if (stringOnly) {
+ // if string only, print content on same line as tags
+ printElementContent(element, out, indentLevel, namespaces, mixedContent);
+ }
+ else {
+ maybePrintln(out);
+ printElementContent(element, out, indentLevel, namespaces, mixedContent);
+ indent(out, indentLevel);
+ }
+
+ out.write("</");
+ out.write(element.getQualifiedName());
+ out.write(">");
+
maybePrintln(out);
- } else if (stringOnly) {
+ }
+
+ // remove declared namespaces from stack
+ while (namespaces.size() > previouslyDeclaredNamespaces) namespaces.pop();
+ }
+
+ /**
+ * <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
+ {
+ List mixedContent = element.getMixedContent();
+ printElementContent(element, out, 0,
+ new NamespaceStack(),
+ mixedContent);
+ }
+
+ /**
+ * <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. */
+ protected void printElementContent(Element element, Writer out,
+ int indentLevel,
+ NamespaceStack namespaces,
+ List mixedContent
+ ) throws IOException
+ {
+ // get same local flags as printElement does
+ // a little redundant code-wise, but not performance-wise
+ 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>
- // Also handle "" being added to content
- String elementText = element.getText();
- if ((elementText != null) && (!elementText.equals(""))) {
- out.write(">");
- out.write(escapeElementEntities(element.getText()));
- out.write("</");
- out.write(element.getQualifiedName());
- out.write(">");
- } else {
- if (!expandEmptyElements) {
- out.write(" />");
- } else {
- out.write("></");
- out.write(element.getQualifiedName());
- out.write(">");
- }
- }
- maybePrintln(out);
+ String elementText =
+ trimText ? element.getTextTrim() : element.getText();
+
+ out.write(escapeElementEntities(elementText));
+
} else {
/**
* Print with children on future lines
@@ -604,8 +707,6 @@
* <child/>
* </tag>
*/
- out.write(">");
- maybePrintln(out);
// Iterate through children
Object content = null;
for (int i=0, size=mixedContent.size(); i<size; i++) {
@@ -626,19 +727,9 @@
} // Unsupported types are *not* printed
}
- indent(out, indentLevel);
- out.write("</");
- out.write(element.getQualifiedName());
- out.write(">");
- maybePrintln(out);
-
}
+ } // printElementContent
- // remove declared namespaces from stack
- while (namespaces.size() > previouslyDeclaredNamespaces) namespaces.pop();
-
- }
-
/**
* <p>
* This will handle printing out an <code>{@link Entity}</code>.
More information about the jdom-interest
mailing list