[jdom-interest] SAXOutputter

Laurent Bihanic laurent.bihanic at atosorigin.com
Mon Apr 19 07:23:36 PDT 2004


Hi,

Chris B. wrote:
> Can somebody please add a method to SAXOutputter to only output a 
> partial JDOM tree (i.e an Element) ?
> 
> I know it has the method output(List), but that is useless because it 
> calls startDocument, which is pretty silly IMO when you are outputting a 
> partial tree.

Attached is a patch proposal that modifies SAXOutputter to :
- make startDocument and endDocument protected final
- add a new public method output(Content) to output a single Content node
- add two new protected methods output(List/Content, boolean fireDocumentEvents)

The last two methods support not firing start/endDocument events when 
fireDocumentEvents is set to false. These methods are protected on purpose : 
To use them, one needs to subclass SAXOutputter which allows to add the logic 
to invoke startDocument and endDocument.

What do you think?

Laurent

-- 
                  wWw
                 (o o)
-------------ooO-(_)-Ooo-----------------------------------------------
Laurent Bihanic                | Tel: +33 (0)1 55.91.21.93 (direct)
AtosOrigin Systems Integration |      +33 (0)1 55.91.20.00
Generic Solutions / SC         | Fax: +33 (0)1 55.91.22.31
Les Miroirs - Bat. C           |
18, avenue d'Alsace            |
F-92926 La Defense Cedex       | E-mail: laurent.bihanic at atosorigin.com
-----------------------------------------------------------------------

I love deadlines. I like the whooshing sound they make as they fly by.


DISCLAIMER:
The opinions expressed are entirely my own and may not necessarily be
those of my employer.  Also, I am not now nor have I ever been a
lawyer.  My opinions are provided as-is with absolutely no warrantee of
merchantability or fitness for any particular use.  Besides, you can't
prove I typed this.  No body saw me type this.  Who says I typed this?
-------------- next part --------------
Index: SAXOutputter.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/output/SAXOutputter.java,v
retrieving revision 1.35
diff -u -r1.35 SAXOutputter.java
--- SAXOutputter.java	27 Feb 2004 11:32:58 -0000	1.35
+++ SAXOutputter.java	19 Apr 2004 16:09:45 -0000
@@ -638,7 +638,7 @@
      * This will output a list of JDOM nodes, firing off the
      * SAX events that have been registered.
      * <p>
-     * <strong>Warning</strong>: This method outputs ill-formed XML
+     * <strong>Warning</strong>: This method may output ill-formed XML
      * documents and should only be used to output document portions
      * towards processors (such as XSLT processors) capable of
      * accepting such ill-formed documents.</p>
@@ -648,6 +648,27 @@
      * @throws JDOMException if any error occurred.
      */
     public void output(List nodes) throws JDOMException {
+       this.output(nodes, true);
+    }
+
+    /**
+     * This will output a list of JDOM nodes, firing off the
+     * SAX events that have been registered.
+     * <p>
+     * <strong>Warning</strong>: This method may output ill-formed XML
+     * documents and should only be used to output document portions
+     * towards processors (such as XSLT processors) capable of
+     * accepting such ill-formed documents.</p>
+     *
+     * @param nodes <code>List</code> of JDOM nodes to output.
+     * @param fireDocumentEvents whether to call the startDocument
+     *        and endDocument ContentHandler calllbacks for this
+     *        document fragment.
+     *
+     * @throws JDOMException if any error occurred.
+     */
+    protected final void output(List nodes, boolean fireDocumentEvents)
+                                                throws JDOMException {
         if ((nodes == null) || (nodes.size() == 0)) {
             return;
         }
@@ -656,13 +677,74 @@
         documentLocator(null);
 
         // contentHandler.startDocument()
-        startDocument();
+        if (fireDocumentEvents) {
+            startDocument();
+        }
 
         // Process node list.
         elementContent(nodes, new NamespaceStack());
 
         // contentHandler.endDocument()
-        endDocument();
+        if (fireDocumentEvents) {
+            endDocument();
+        }
+    }
+
+
+    /**
+     * This will output a single JDOM node, firing off the
+     * SAX events that have been registered.
+     * <p>
+     * <strong>Warning</strong>: This method may output ill-formed XML
+     * documents and should only be used to output document portions
+     * towards processors (such as XSLT processors) capable of
+     * accepting such ill-formed documents.</p>
+     *
+     * @param node the <code>Content</code> node to output.
+     *
+     * @throws JDOMException if any error occurred.
+     */
+    public void output(Content node) throws JDOMException {
+       this.output(node, true);
+    }
+
+    /**
+     * This will output a single JDOM node, firing off the
+     * SAX events that have been registered.
+     * <p>
+     * <strong>Warning</strong>: This method may output ill-formed XML
+     * documents and should only be used to output document portions
+     * towards processors (such as XSLT processors) capable of
+     * accepting such ill-formed documents.</p>
+     *
+     * @param node the <code>Content</code> node to output.
+     * @param fireDocumentEvents whether to call the startDocument
+     *        and endDocument ContentHandler calllbacks for this
+     *        document fragment.
+     *
+     * @throws JDOMException if any error occurred.
+     */
+    protected final void output(Content node, boolean fireDocumentEvents)
+                                                throws JDOMException {
+        if (node == null) {
+            return;
+        }
+
+        // contentHandler.setDocumentLocator()
+        documentLocator(null);
+
+        // contentHandler.startDocument()
+        if (fireDocumentEvents) {
+            startDocument();
+        }
+
+        // Process node list.
+        elementContent(node, new NamespaceStack());
+
+        // contentHandler.endDocument()
+        if (fireDocumentEvents) {
+            endDocument();
+        }
     }
 
     /**
@@ -772,7 +854,7 @@
      * all handlers to be invoked (setDocumentLocator is always first).
      * </p>
      */
-    private void startDocument() throws JDOMException {
+    protected final void startDocument() throws JDOMException {
         try {
             contentHandler.startDocument();
         }
@@ -787,7 +869,7 @@
      * to be invoked.
      * </p>
      */
-    private void endDocument() throws JDOMException {
+    protected final void endDocument() throws JDOMException {
         try {
             contentHandler.endDocument();
 
@@ -1009,34 +1091,11 @@
      */
     private void elementContent(List content, NamespaceStack namespaces)
                       throws JDOMException {
-        Iterator i = content.iterator();
-        while (i.hasNext()) {
+        for (Iterator i=content.iterator(); i.hasNext(); ) {
             Object obj = i.next();
 
-            // update locator
-            locator.setNode(obj);
-
-            if (obj instanceof Element) {
-                element((Element) obj, namespaces);
-            }
-            else if (obj instanceof CDATA) {
-                cdata(((CDATA) obj).getText());
-            }
-            else if (obj instanceof Text) {
-                // contentHandler.characters()
-                characters(((Text) obj).getText());
-            }
-            else if (obj instanceof ProcessingInstruction) {
-                // contentHandler.processingInstruction()
-                processingInstruction((ProcessingInstruction) obj);
-            }
-            else if (obj instanceof Comment) {
-                // lexicalHandler.comment()
-                comment(((Comment) obj).getText());
-            }
-            else if (obj instanceof EntityRef) {
-                // contentHandler.skippedEntity()
-                entityRef((EntityRef) obj);
+            if (obj instanceof Content) {
+                this.elementContent((Content)obj, namespaces);
             }
             else {
                 // Not a valid element child. This could happen with
@@ -1045,6 +1104,49 @@
                 handleError(new JDOMException(
                                         "Invalid element content: " + obj));
             }
+        }
+    }
+
+    /**
+     * <p>
+     * This will invoke the callbacks for the content of an element.
+     * </p>
+     *
+     * @param node a <code>Content</code> node.
+     * @param namespaces <code>List</code> stack of Namespaces in scope.
+     */
+    private void elementContent(Content node, NamespaceStack namespaces)
+                      throws JDOMException {
+        // update locator
+        locator.setNode(node);
+
+        if (node instanceof Element) {
+            element((Element) node, namespaces);
+        }
+        else if (node instanceof CDATA) {
+            cdata(((CDATA) node).getText());
+        }
+        else if (node instanceof Text) {
+            // contentHandler.characters()
+            characters(((Text) node).getText());
+        }
+        else if (node instanceof ProcessingInstruction) {
+            // contentHandler.processingInstruction()
+            processingInstruction((ProcessingInstruction) node);
+        }
+        else if (node instanceof Comment) {
+            // lexicalHandler.comment()
+            comment(((Comment) node).getText());
+        }
+        else if (node instanceof EntityRef) {
+            // contentHandler.skippedEntity()
+            entityRef((EntityRef) node);
+        }
+        else {
+            // Not a valid element child. This could happen with
+            // application-provided lists which may contain non
+            // JDOM objects.
+            handleError(new JDOMException("Invalid element content: " + node));
         }
     }
 


More information about the jdom-interest mailing list