cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [69/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/...
Date Thu, 03 Nov 2005 14:00:48 GMT
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLUtils.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLUtils.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLUtils.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLUtils.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,674 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.xml;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.xml.dom.DOMStreamer;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * XML utility methods.
+ *
+ * @author <a href="mailto:barozzi@nicolaken.com">Nicola Ken Barozzi</a>
+ * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
+ * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
+ * @version $Id: XMLUtils.java 164043 2005-04-21 12:11:55Z vgritsenko $
+ */
+public class XMLUtils {
+
+    /**
+     * Empty attributes immutable object.
+     */
+    public static final Attributes EMPTY_ATTRIBUTES = new ImmutableAttributesImpl();
+
+    private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+    private static final Properties XML_FORMAT = createDefaultPropertiesForXML(false);
+    private static final Properties XML_FORMAT_NODECL = createDefaultPropertiesForXML(true);
+
+
+    // FIXME: parent parameter not used anymore
+    // Using parent because some dom implementations like jtidy are bugged,
+    // cannot get parent or delete child
+    public static void stripDuplicateAttributes(Node node, Node parent) {
+
+        // The output depends on the type of the node
+        switch(node.getNodeType()) {
+        case Node.DOCUMENT_NODE: {
+            Document doc = (Document)node;
+            Node child = doc.getFirstChild();
+            while(child != null) {
+                stripDuplicateAttributes(child, node);
+                child = child.getNextSibling();
+            }
+            break;
+        }
+
+        case Node.ELEMENT_NODE: {
+            Element elt = (Element) node;
+            NamedNodeMap attrs = elt.getAttributes();
+
+            ArrayList nodesToRemove = new ArrayList();
+            int nodesToRemoveNum = 0;
+
+            for (int i = 0; i < attrs.getLength(); i++) {
+                final Node a = attrs.item(i);
+
+                for (int j = 0; j < attrs.getLength(); j++) {
+                    final Node b = attrs.item(j);
+
+                    //if there are two attributes with same name
+                    if (i != j && (a.getNodeName().equals(b.getNodeName()))) {
+                        nodesToRemove.add(b);
+                        nodesToRemoveNum++;
+                    }
+                }
+            }
+
+            for (int i = 0; i < nodesToRemoveNum; i++) {
+                org.w3c.dom.Attr nodeToDelete = (org.w3c.dom.Attr) nodesToRemove.get(i);
+                org.w3c.dom.Element nodeToDeleteParent = (org.w3c.dom.Element) node; // nodeToDelete.getParentNode();
+                nodeToDeleteParent.removeAttributeNode(nodeToDelete);
+            }
+
+            nodesToRemove.clear();
+
+            Node child = elt.getFirstChild();
+            while (child != null) {
+                stripDuplicateAttributes(child, node);
+                child = child.getNextSibling();
+            }
+
+            break;
+        }
+
+        default:
+            //do nothing
+            break;
+        }
+    }
+
+    /**
+     * Get an <code>XMLConsumer</code> from a <code>ContentHandler</code> and
+     * a <code>LexicalHandler</code>. If the content handler is already an
+     * <code>XMLConsumer</code>, it is returned as is, otherwise it is wrapped
+     * in an <code>XMLConsumer</code> with the lexical handler.
+     *
+     * @param ch the content handler, which should not be <code>null</code>
+     * @param lh the lexical handler, which can be <code>null</code>
+     * @return an <code>XMLConsumer</code> for <code>ch</code> an <code>lh</code>
+     */
+    public static XMLConsumer getConsumer(ContentHandler ch, LexicalHandler lh) {
+        if (ch instanceof XMLConsumer) {
+            return (XMLConsumer)ch;
+        } else {
+            if ( lh == null && ch instanceof LexicalHandler ) {
+                lh = (LexicalHandler)ch;
+            }
+            return new ContentHandlerWrapper(ch, lh);
+        }
+    }
+
+    /**
+     * Get an <code>XMLConsumer</code> from <code>ContentHandler</code>. If the
+     * content handler is already an <code>XMLConsumer</code>, it is returned as
+     * is, otherwise it is wrapped in an <code>XMLConsumer</code>.
+     *
+     * @param ch the content handler, which should not be <code>null</code>
+     * @return an <code>XMLConsumer</code> for <code>ch</code>
+     */
+    public static XMLConsumer getConsumer(ContentHandler ch) {
+        return getConsumer(ch, null);
+    }
+
+    /**
+     * Method for static initializer
+     */
+    private static Properties createDefaultPropertiesForXML(boolean omitXMLDeclaration) {
+        final Properties format = new Properties();
+        format.put(OutputKeys.METHOD, "xml");
+        format.put(OutputKeys.OMIT_XML_DECLARATION, (omitXMLDeclaration ? "yes" : "no"));
+        format.put(OutputKeys.INDENT, "yes");
+        return format;
+    }
+
+    /**
+     * Create a new properties set for serializing xml.
+     * The omit xml declaration property can be controlled by the flag.
+     *
+     * <ul>
+     * <li>Method: xml
+     * <li>Omit xml declaration: according to the flag
+     * <li>Indent: yes
+     * </ul>
+     */
+    public static Properties createPropertiesForXML(boolean omitXMLDeclaration) {
+        return new Properties(omitXMLDeclaration? XML_FORMAT_NODECL: XML_FORMAT);
+    }
+
+    /**
+     * Serialize a DOM node into a string using format created by
+     * <code>createPropertiesForXML(false)</code>.
+     *
+     * @see #createPropertiesForXML
+     */
+    public static String serializeNode(Node node)
+    throws ProcessingException {
+        // Don't create new properties as we do not intend to modify defaults.
+        return serializeNode(node, XML_FORMAT);
+    }
+
+    /**
+     * Serialize a DOM node into a string.
+     * If the node is null the empty string is returned.
+     *
+     * @param format The format of the output to be used by SAX transformer.
+     * @see OutputKeys
+     */
+    public static String serializeNode(Node node, Properties format)
+    throws ProcessingException {
+
+        try {
+            if (node == null) {
+                return "";
+            }
+
+            StringWriter writer = new StringWriter();
+            TransformerHandler transformerHandler;
+            transformerHandler = FACTORY.newTransformerHandler();
+            transformerHandler.getTransformer().setOutputProperties(format);
+            transformerHandler.setResult(new StreamResult(writer));
+            if (node.getNodeType() != Node.DOCUMENT_NODE) {
+                transformerHandler.startDocument();
+            }
+            DOMStreamer domStreamer = new DOMStreamer(transformerHandler, transformerHandler);
+            domStreamer.stream(node);
+            if (node.getNodeType() != Node.DOCUMENT_NODE) {
+                transformerHandler.endDocument();
+            }
+
+            return writer.toString();
+        } catch (javax.xml.transform.TransformerException e) {
+            throw new ProcessingException("TransformerException: " + e, e);
+        } catch (SAXException e) {
+            throw new ProcessingException("SAXException while streaming DOM node to SAX: " + e, e);
+        }
+    }
+
+    /**
+     * Serialize a XMLizable into a string.
+     * If the object is null the empty string is returned.
+     *
+     * @param format The format of the output to be used by SAX transformer.
+     * @see OutputKeys
+     */
+    public static String serialize(org.apache.excalibur.xml.sax.XMLizable xml, Properties format)
+    throws ProcessingException {
+        
+        try {
+            if (xml == null) {
+                return "";
+            }
+
+            StringWriter writer = new StringWriter();
+            TransformerHandler transformerHandler;
+            transformerHandler = FACTORY.newTransformerHandler();
+            transformerHandler.getTransformer().setOutputProperties(format);
+            transformerHandler.setResult(new StreamResult(writer));
+            transformerHandler.startDocument();
+            xml.toSAX(new EmbeddedXMLPipe(transformerHandler));
+            transformerHandler.endDocument();
+
+            return writer.toString();
+        } catch (javax.xml.transform.TransformerException e) {
+            throw new ProcessingException("TransformerException: " + e, e);
+        } catch (SAXException e) {
+            throw new ProcessingException("SAXException while streaming DOM node to SAX: " + e, e);
+        }
+    }
+
+    /**
+     * Add string data
+     *
+     * @param contentHandler The SAX content handler
+     * @param data The string data
+     */
+    public static void data(ContentHandler contentHandler,
+                            String data)
+    throws SAXException {
+
+        contentHandler.characters(data.toCharArray(), 0, data.length());
+    }
+
+    /**
+     * Implementation of &lt;xsp:expr&gt; for <code>String</code> :
+     * outputs characters representing the value.
+     *
+     * @param contentHandler the SAX content handler
+     * @param text the value
+     */
+    public static void valueOf(ContentHandler contentHandler, String text)
+    throws SAXException {
+
+        if (text != null) {
+            data(contentHandler, text);
+        }
+    }
+
+    /**
+     * Implementation of &lt;xsp:expr&gt; for <code>XMLizable</code> :
+     * outputs the value by calling <code>v.toSax(contentHandler)</code>.
+     *
+     * @param contentHandler the SAX content handler
+     * @param v the XML fragment
+     */
+    public static void valueOf(ContentHandler contentHandler,
+                               org.apache.excalibur.xml.sax.XMLizable v)
+    throws SAXException {
+
+        if (v != null) {
+            v.toSAX(contentHandler);
+        }
+    }
+
+    /**
+     * Implementation of &lt;xsp:expr&gt; for <code>org.w3c.dom.Node</code> :
+     * converts the Node to a SAX event stream.
+     *
+     * @param contentHandler the SAX content handler
+     * @param v the value
+     */
+    public static void valueOf(ContentHandler contentHandler, Node v)
+    throws SAXException {
+
+        if (v != null) {
+            DOMStreamer streamer = new DOMStreamer(contentHandler);
+            if (contentHandler instanceof LexicalHandler) {
+                streamer.setLexicalHandler((LexicalHandler)contentHandler);
+            }
+            streamer.stream(v);
+        }
+    }
+
+    /**
+     * Implementation of &lt;xsp:expr&gt; for <code>java.util.Collection</code> :
+     * outputs the value by calling <code>xspExpr()</code> on each element of the
+     * collection.
+     *
+     * @param contentHandler the SAX content handler
+     * @param v the XML fragment
+     */
+    public static void valueOf(ContentHandler contentHandler,
+                               Collection v)
+    throws SAXException {
+
+        if (v != null) {
+            Iterator iterator = v.iterator();
+            while (iterator.hasNext()) {
+                valueOf(contentHandler, iterator.next());
+            }
+        }
+     }
+
+    /**
+     * Implementation of &lt;xsp:expr&gt; for <code>Object</code> depending on its class :
+     * <ul>
+     * <li>if it's an array, call <code>xspExpr()</code> on all its elements,</li>
+     * <li>if it's class has a specific <code>xspExpr()</code>implementation, use it,</li>
+     * <li>else, output it's string representation.</li>
+     * </ul>
+     *
+     * @param contentHandler the SAX content handler
+     * @param v the value
+     */
+    public static void valueOf(ContentHandler contentHandler, Object v)
+    throws SAXException {
+
+        if (v == null) {
+            return;
+        }
+
+        // Array: recurse over each element
+        if (v.getClass().isArray()) {
+            Object[] elements = (Object[]) v;
+
+            for (int i = 0; i < elements.length; i++) {
+                valueOf(contentHandler, elements[i]);
+            }
+            return;
+         }
+
+         // Check handled object types in case they were not typed in the XSP
+
+         // XMLizable
+         if (v instanceof org.apache.excalibur.xml.sax.XMLizable) {
+             valueOf(contentHandler, (org.apache.excalibur.xml.sax.XMLizable)v);
+             return;
+         }
+
+         // Node
+         if (v instanceof Node) {
+             valueOf(contentHandler, (Node)v);
+             return;
+         }
+
+         // Collection
+         if (v instanceof Collection) {
+             valueOf(contentHandler, (Collection)v);
+             return;
+         }
+
+         // Give up: hope it's a string or has a meaningful string representation
+         data(contentHandler, String.valueOf(v));
+    }
+
+    /**
+     * Create a start and endElement with a empty Namespace and without Attributes
+     *
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void createElement(ContentHandler contentHandler,
+                                     String localName)
+    throws SAXException {
+
+        startElement(contentHandler, localName);
+        endElement(contentHandler, localName);
+    }
+
+    /**
+     * Create a start and endElement with a empty Namespace and without Attributes
+     * The content of the Element is set to the stringValue parameter
+     *
+     * @param localName The local name (without prefix)
+     * @param stringValue The content of the Element
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void createElement(ContentHandler contentHandler,
+                                     String localName,
+                                     String stringValue)
+    throws SAXException {
+
+        startElement(contentHandler, localName);
+        data(contentHandler, stringValue);
+        endElement(contentHandler, localName);
+    }
+
+    /**
+     * Create a start and endElement with a empty Namespace
+     *
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void createElement(ContentHandler contentHandler,
+                                     String localName,
+                                     Attributes atts)
+    throws SAXException {
+
+        startElement(contentHandler, localName, atts);
+        endElement(contentHandler, localName);
+    }
+
+    /**
+     * Create a start and endElement with a empty Namespace
+     * The content of the Element is set to the stringValue parameter
+     *
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @param stringValue The content of the Element
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void createElement(ContentHandler contentHandler,
+                                     String localName,
+                                     Attributes atts,
+                                     String stringValue)
+    throws SAXException {
+
+        startElement(contentHandler, localName, atts);
+        data(contentHandler, stringValue);
+        endElement(contentHandler, localName);
+    }
+
+    /**
+     * Create a start and endElement without Attributes
+     *
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void createElementNS(ContentHandler contentHandler,
+                                       String namespaceURI,
+                                       String localName)
+    throws SAXException {
+
+        startElement(contentHandler, namespaceURI, localName);
+        endElement(contentHandler, namespaceURI, localName);
+    }
+
+    /**
+     * Create a start and endElement without Attributes
+     * The content of the Element is set to the stringValue parameter
+     *
+     * @param localName The local name (without prefix)
+     * @param stringValue The content of the Element
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void createElementNS(ContentHandler contentHandler,
+                                       String namespaceURI,
+                                       String localName,
+                                       String stringValue)
+    throws SAXException {
+
+        startElement(contentHandler, namespaceURI, localName);
+        data(contentHandler, stringValue);
+        endElement(contentHandler, namespaceURI, localName);
+    }
+
+    /**
+     * Create a start and endElement
+     *
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void createElementNS(ContentHandler contentHandler,
+                                       String namespaceURI,
+                                       String localName,
+                                       Attributes atts)
+    throws SAXException {
+
+        startElement(contentHandler, namespaceURI, localName, atts);
+        endElement(contentHandler, namespaceURI, localName);
+    }
+
+    /**
+     * Create a start and endElement with a empty Namespace
+     * The content of the Element is set to the stringValue parameter
+     *
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @param stringValue The content of the Element
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void createElementNS(ContentHandler contentHandler,
+                                       String namespaceURI,
+                                       String localName,
+                                       Attributes atts,
+                                       String stringValue)
+    throws SAXException {
+
+        startElement(contentHandler, namespaceURI, localName, atts);
+        data(contentHandler, stringValue);
+        endElement(contentHandler, namespaceURI, localName);
+    }
+
+
+    /**
+     * Create endElement with empty Namespace
+     *
+     * <p>For information on the names, see startElement.</p>
+     *
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public static void endElement(ContentHandler contentHandler,
+                                  String localName)
+    throws SAXException {
+
+        contentHandler.endElement("", localName, localName);
+    }
+
+    /**
+     * Create endElement
+     * Prefix must be mapped to empty String
+     *
+     * <p>For information on the names, see startElement.</p>
+     *
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     */
+    public static void endElement(ContentHandler contentHandler,
+                                  String namespaceURI,
+                                  String localName)
+    throws SAXException {
+
+        contentHandler.endElement(namespaceURI, localName, localName);
+    }
+
+    /**
+     * Create a startElement with a empty Namespace and without Attributes
+     *
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void startElement(ContentHandler contentHandler,
+                                    String localName)
+    throws SAXException {
+
+        contentHandler.startElement("", localName, localName, EMPTY_ATTRIBUTES);
+    }
+
+    /**
+     * Create a startElement without Attributes
+     * Prefix must be mapped to empty String
+     *
+     * @param namespaceURI The Namespace URI
+     * @param localName The local name (without prefix)
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     */
+    public static void startElement(ContentHandler contentHandler,
+                                    String namespaceURI,
+                                    String localName)
+    throws SAXException {
+
+        contentHandler.startElement(namespaceURI, localName, localName, EMPTY_ATTRIBUTES);
+    }
+
+    /**
+     * Create a startElement with a empty Namespace
+     *
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void startElement(ContentHandler contentHandler,
+                                    String localName,
+                                    Attributes atts)
+    throws SAXException {
+
+        contentHandler.startElement("", localName, localName, atts);
+    }
+
+    /**
+     * Create a startElement with a empty Namespace
+     * Prefix must be mapped to empty String
+     *
+     * @param namespaceURI The Namespace URI
+     * @param localName The local name (without prefix)
+     * @param atts The attributes attached to the element.  If
+     *        there are no attributes, it shall be an empty
+     *        Attributes object.
+     * @exception org.xml.sax.SAXException Any SAX exception, possibly
+     *            wrapping another exception.
+     * @see #endElement(ContentHandler, String)
+     * @see org.xml.sax.Attributes
+     */
+    public static void startElement(ContentHandler contentHandler,
+                                    String namespaceURI,
+                                    String localName,
+                                    Attributes atts)
+    throws SAXException {
+
+        contentHandler.startElement(namespaceURI, localName, localName, atts);
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/XMLUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMBuilder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMBuilder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMBuilder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,176 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.xml.dom;
+
+import org.apache.avalon.framework.CascadingRuntimeException;
+
+import org.apache.cocoon.xml.AbstractXMLPipe;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+
+/**
+ * The <code>DOMBuilder</code> is a utility class that will generate a W3C
+ * DOM Document from SAX events.
+ *
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @version $Id: DOMBuilder.java 164048 2005-04-21 12:35:57Z vgritsenko $
+ */
+public class DOMBuilder extends AbstractXMLPipe {
+
+    /** The default transformer factory shared by all instances */
+    protected static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+
+    /** The transformer factory */
+    protected SAXTransformerFactory factory;
+
+    /** The listener */
+    protected Listener listener;
+
+    /** The result */
+    protected DOMResult result;
+
+    /** The parentNode */
+    protected Node parentNode;
+
+    /**
+     * Construct a new instance of this DOMBuilder.
+     */
+    public DOMBuilder() {
+        this((Listener) null, (Node) null);
+    }
+
+    /**
+     * Construct a new instance of this DOMBuilder.
+     */
+    public DOMBuilder(SAXTransformerFactory factory) {
+        this(factory, null, null);
+    }
+
+    /**
+     * Construct a new instance of this DOMBuilder.
+     */
+    public DOMBuilder(Listener listener) {
+        this(listener, null);
+    }
+
+    /**
+     * Constructs a new instance that appends nodes to the given parent node.
+     * <br/>
+     * <strong>Note:</strong> You cannot use a <code>Listener<code> when appending to a
+     * <code>Node</code>, because the notification occurs at <code>endDocument()</code>
+     * which does not happen here.
+     */
+    public DOMBuilder(Node parentNode) {
+        this(null, parentNode);
+    }
+
+    /**
+     * Construct a new instance of this DOMBuilder.
+     */
+    public DOMBuilder(Listener listener, Node parentNode) {
+        this((SAXTransformerFactory) null, listener, parentNode);
+    }
+
+    /**
+     * Construct a new instance of this DOMBuilder.
+     */
+    public DOMBuilder(SAXTransformerFactory factory, Listener listener, Node parentNode) {
+        super();
+        this.factory = factory == null? FACTORY: factory;
+        this.listener = listener;
+        this.parentNode = parentNode;
+        setup();
+    }
+
+    /**
+     * Setup this instance transformer and result objects.
+     */
+    private void setup() {
+        try {
+            TransformerHandler handler = this.factory.newTransformerHandler();
+            setContentHandler(handler);
+            setLexicalHandler(handler);
+            if (this.parentNode != null) {
+                this.result = new DOMResult(this.parentNode);
+            } else {
+                this.result = new DOMResult();
+            }
+            handler.setResult(this.result);
+        } catch (javax.xml.transform.TransformerException local) {
+            throw new CascadingRuntimeException("Fatal-Error: Unable to get transformer handler", local);
+        }
+    }
+
+    /**
+     * Recycle this builder, prepare for re-use.
+     */
+    public void recycle() {
+        super.recycle();
+        setup();
+    }
+
+    /**
+     * Return the newly built Document.
+     */
+    public Document getDocument() {
+        if (this.result == null || this.result.getNode() == null) {
+            return null;
+        } else if (this.result.getNode().getNodeType() == Node.DOCUMENT_NODE) {
+            return (Document) this.result.getNode();
+        } else {
+            return this.result.getNode().getOwnerDocument();
+        }
+    }
+
+    /**
+     * Receive notification of the end of a document.
+     *
+     * @exception SAXException If this method was not called appropriately.
+     */
+    public void endDocument() throws SAXException {
+        super.endDocument();
+        // Notify the listener
+        notifyListener();
+    }
+
+    /**
+     * Receive notification of a successfully completed DOM tree generation.
+     */
+    protected void notifyListener() throws SAXException {
+        if (this.listener != null) {
+            this.listener.notify(getDocument());
+        }
+    }
+
+    /**
+     * The Listener interface must be implemented by those objects willing to
+     * be notified of a successful DOM tree generation.
+     */
+    public interface Listener {
+
+        /**
+         * Receive notification of a successfully completed DOM tree generation.
+         */
+        void notify(Document doc) throws SAXException;
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMFactory.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMFactory.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMFactory.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMFactory.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.xml.dom;
+
+import org.w3c.dom.Document;
+
+/**
+ * This interface identifies classes producing instances of DOM
+ * <code>Document</code> objects.
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @version CVS $Id: DOMFactory.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public interface DOMFactory {
+    /**
+     * Create a new Document object.
+     */
+    Document newDocument();
+
+    /**
+     * Create a new Document object with a specified DOCTYPE.
+     */
+    Document newDocument(String name);
+
+    /**
+     * Create a new Document object with a specified DOCTYPE, public ID and
+     * system ID.
+     */
+    Document newDocument(String name, String publicId, String systemId);
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMStreamer.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMStreamer.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMStreamer.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMStreamer.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,725 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.xml.dom;
+
+import org.apache.avalon.excalibur.pool.Recyclable;
+
+import org.apache.cocoon.xml.AbstractXMLProducer;
+import org.apache.cocoon.xml.EmbeddedXMLPipe;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.XMLProducer;
+
+import org.apache.commons.lang.StringUtils;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * The <code>DOMStreamer</code> is a utility class that will generate SAX
+ * events from a W3C DOM Document.
+ *
+ * <p>The DOMStreamer uses a different strategy based on the value of the
+ * normalizeNamespaces property:
+ * <ul>
+ * <li>if true (the default), the DOMStreamer will normalize namespace
+ * declarations (i.e. add missing xmlns attributes or correct them). See
+ * also {@link NamespaceNormalizingDOMStreamer}.
+ * <li>if false, the standard JAXP identity transformer is used.
+ * </ul>
+ *
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @version $Id: DOMStreamer.java 164222 2005-04-22 11:41:51Z cziegeler $
+ */
+public class DOMStreamer implements XMLProducer, Recyclable {
+
+    /** The transformer factory shared by all instances (only used by DefaultDOMStreamer) */
+    protected static final TransformerFactory FACTORY = TransformerFactory.newInstance();
+
+    /** Default value for normalizeNamespaces. */
+    private static final boolean DEFAULT_NORMALIZE_NAMESPACES = true;
+
+    /** Indicates whether namespace normalization should happen. */
+    protected boolean normalizeNamespaces = DEFAULT_NORMALIZE_NAMESPACES;
+
+    /** DOMStreamer used in case of namespace normalization. */
+    protected NamespaceNormalizingDOMStreamer namespaceNormalizingDOMStreamer = new NamespaceNormalizingDOMStreamer();
+
+    /** DOMStreamer used when namespace normalization should not explicitely happen. */
+    protected DefaultDOMStreamer defaultDOMStreamer = new DefaultDOMStreamer();
+
+    /**
+     * Create a new <code>DOMStreamer</code> instance.
+     */
+    public DOMStreamer() {
+        super();
+    }
+
+    /**
+     * Create a new <code>DOMStreamer</code> instance.
+     */
+    public DOMStreamer(ContentHandler content, LexicalHandler lexical) {
+        this();
+        setContentHandler(content);
+        setLexicalHandler(lexical);
+    }
+
+    /**
+     * Create a new <code>DOMStreamer</code> instance.
+     */
+    public DOMStreamer(XMLConsumer consumer) {
+        this(consumer, consumer);
+    }
+
+    /**
+     * Create a new <code>DOMStreamer</code> instance.
+     */
+    public DOMStreamer(ContentHandler content) {
+        this(content, content instanceof LexicalHandler ? (LexicalHandler) content : null);
+    }
+
+    /**
+     * Set the <code>XMLConsumer</code> that will receive XML data.
+     */
+    public void setConsumer(XMLConsumer consumer) {
+        setContentHandler(consumer);
+        setLexicalHandler(consumer);
+    }
+
+    /**
+     * Set the <code>ContentHandler</code> that will receive XML data.
+     */
+    public void setContentHandler(ContentHandler handler) {
+        defaultDOMStreamer.setContentHandler(handler);
+        namespaceNormalizingDOMStreamer.setContentHandler(handler);
+    }
+
+    /**
+     * Set the <code>LexicalHandler</code> that will receive XML data.
+     */
+    public void setLexicalHandler(LexicalHandler handler) {
+        defaultDOMStreamer.setLexicalHandler(handler);
+        namespaceNormalizingDOMStreamer.setLexicalHandler(handler);
+    }
+
+    /**
+     * Start the production of SAX events.
+     */
+    public void stream(Node node) throws SAXException {
+        if (normalizeNamespaces) {
+            namespaceNormalizingDOMStreamer.stream(node);
+        } else {
+            defaultDOMStreamer.stream(node);
+        }
+    }
+
+    public boolean isNormalizeNamespaces() {
+        return normalizeNamespaces;
+    }
+
+    public void setNormalizeNamespaces(boolean normalizeNamespaces) {
+        this.normalizeNamespaces = normalizeNamespaces;
+    }
+
+    public void recycle() {
+        defaultDOMStreamer.recycle();
+        namespaceNormalizingDOMStreamer.recycle();
+        normalizeNamespaces = DEFAULT_NORMALIZE_NAMESPACES;
+    }
+
+    /**
+     * Streams a DOM tree to SAX events and normalizes namespace declarations on the way.
+     *
+     * <p>The code in this class is based on the org.apache.xml.utils.TreeWalker class from Xalan,
+     * though it differs in some important ways.
+     *
+     * <p>This class will automatically fix up ("normalize") namespace declarations
+     * while streaming to SAX. The original DOM-tree is not modified. The algorithm
+     * used is described in
+     * <a href="http://www.w3.org/TR/2002/WD-DOM-Level-3-Core-20021022/namespaces-algorithms.html#normalizeDocumentAlgo">an appendix of the DOM Level 3 spec</a>.
+     *
+     * <p>This class will NOT check the correctness of namespaces, e.g. it will not
+     * check that the "xml" prefix is not misused etc.
+     *
+     * @author Bruno Dumon (bruno at outerthought dot org)
+     * @author Xalan team
+     */
+    public static class NamespaceNormalizingDOMStreamer extends AbstractXMLProducer {
+        /**
+         * Information about the current element. Used to remember the localName, qName
+         * and namespaceURI for generating the endElement event, and holds the namespaces
+         * declared on the element. This extra class is needed because we don't want to
+         * modify the DOM-tree itself. The currentElementInfo has a pointer to its parent
+         * elementInfo.
+         */
+        protected NamespaceNormalizingDOMStreamer.ElementInfo currentElementInfo;
+
+        /** Counter used when generating new namespace prefixes. */
+        protected int newPrefixCounter;
+
+        public void recycle() {
+            super.recycle();
+            currentElementInfo = null;
+            newPrefixCounter = 0;
+        }
+
+        /**
+         * Start the production of SAX events.
+         *
+         * <p>Perform a pre-order traversal non-recursive style.
+         *
+         * <p>Note that TreeWalker assumes that the subtree is intended to represent
+         * a complete (though not necessarily well-formed) document and, during a
+         * traversal, startDocument and endDocument will always be issued to the
+         * SAX listener.
+         *
+         * @param pos Node in the tree where to start traversal
+         */
+        protected void stream(Node pos) throws SAXException {
+
+            // Start document only if we're streaming a document
+            boolean isDoc = (pos.getNodeType() == Node.DOCUMENT_NODE);
+            if (isDoc) {
+              contentHandler.startDocument();
+            }
+
+            Node top = pos;
+            while (null != pos) {
+                startNode(pos);
+
+                Node nextNode = pos.getFirstChild();
+                while (null == nextNode) {
+                    endNode(pos);
+
+                    if (top.equals(pos)) {
+                        break;
+                    }
+
+                    nextNode = pos.getNextSibling();
+                    if (null == nextNode) {
+                        pos = pos.getParentNode();
+
+                        if ((null == pos) || (top.equals(pos))) {
+                            if (null != pos) {
+                                endNode(pos);
+                            }
+                            nextNode = null;
+
+                            break;
+                        }
+                    }
+                }
+
+                pos = nextNode;
+            }
+
+            if (isDoc) {
+            	contentHandler.endDocument();
+            }
+        }
+
+        private final void dispatchChars(Node node) throws SAXException {
+            final String data = ((Text) node).getData();
+            if ( data != null ) {
+                contentHandler.characters(data.toCharArray(), 0, data.length());
+            }
+        }
+
+        /**
+         * Start processing given node
+         *
+         * @param node Node to process
+         */
+        protected void startNode(Node node) throws SAXException {
+
+            switch (node.getNodeType()) {
+                case Node.COMMENT_NODE:
+                    {
+                        if (lexicalHandler != null) {
+                            final String data = ((Comment) node).getData();
+                            if ( data != null ) {
+                                lexicalHandler.comment(data.toCharArray(), 0, data.length());
+                            }
+                        }
+                    }
+                    break;
+                case Node.DOCUMENT_FRAGMENT_NODE:
+
+                    // ??;
+                    break;
+                case Node.DOCUMENT_NODE:
+
+                    break;
+                case Node.ELEMENT_NODE:
+                    NamedNodeMap atts = node.getAttributes();
+                    int nAttrs = atts.getLength();
+
+                    // create a list of localy declared namespace prefixes
+                    currentElementInfo = new NamespaceNormalizingDOMStreamer.ElementInfo(currentElementInfo);
+                    for (int i = 0; i < nAttrs; i++) {
+                        Node attr = atts.item(i);
+                        String attrName = attr.getNodeName();
+
+                        if (attrName.equals("xmlns") || attrName.startsWith("xmlns:")) {
+                            int index;
+                            String prefix = (index = attrName.indexOf(":")) < 0
+                                    ? "" : attrName.substring(index + 1);
+
+                            currentElementInfo.put(prefix, attr.getNodeValue());
+                        }
+                    }
+
+                    String namespaceURI = node.getNamespaceURI();
+                    String prefix = node.getPrefix();
+                    String localName = node.getLocalName();
+
+                    if (localName == null) {
+                        // this is an element created with createElement instead of createElementNS
+                        String[] prefixAndLocalName = getPrefixAndLocalName(node.getNodeName());
+                        prefix = prefixAndLocalName[0];
+                        localName = prefixAndLocalName[1];
+                        // note: if prefix is null, there can still be a default namespace...
+                        namespaceURI = getNamespaceForPrefix(prefix, (Element)node);
+                    }
+
+                    if (namespaceURI != null) {
+                        // no prefix means: make this the default namespace
+                        if (prefix == null) {
+                            prefix = "";
+                        }
+                        // check that is declared
+                        String uri = currentElementInfo.findNamespaceURI(prefix);
+                        if (StringUtils.equals(uri, namespaceURI)) {
+                            // System.out.println("namespace is declared");
+                            // prefix is declared correctly, do nothing
+                        } else if (uri != null) {
+                            // System.out.println("prefix is declared with other namespace, overwriting it");
+                            // prefix exists but is bound to another namespace, overwrite it
+                            currentElementInfo.put(prefix, namespaceURI);
+                        } else {
+                            // System.out.println("prefix is not yet declared, declaring it now");
+                            currentElementInfo.put(prefix, namespaceURI);
+                        }
+                    } else {
+                        // element has no namespace
+                        // check if there is a default namespace, if so undeclare it
+                        String uri = currentElementInfo.findNamespaceURI("");
+                        if (StringUtils.isNotEmpty(uri)) {
+                            // System.out.println("undeclaring default namespace");
+                            currentElementInfo.put("", "");
+                        }
+                    }
+
+                    // SAX uses empty string to denote no namespace, while DOM uses null.
+                    if (namespaceURI == null)
+                        namespaceURI = "";
+
+                    String qName;
+                    if (StringUtils.isNotEmpty(prefix)) {
+                        qName = prefix + ":" + localName;
+                    } else {
+                        qName = localName;
+                    }
+
+                    // make the attributes
+                    AttributesImpl newAttrs = new AttributesImpl();
+                    for (int i = 0; i < nAttrs; i++) {
+                        Node attr = atts.item(i);
+                        String attrName = attr.getNodeName();
+                        String assignedAttrPrefix = null;
+
+                        // only do non-namespace attributes
+                        if (!(attrName.equals("xmlns") || attrName.startsWith("xmlns:"))) {
+                            String attrPrefix;
+                            String attrLocalName;
+                            String attrNsURI;
+
+                            if (attr.getLocalName() == null) {
+                                // this is an attribute created with setAttribute instead of setAttributeNS
+                                String[] prefixAndLocalName = getPrefixAndLocalName(attrName);
+                                attrPrefix = prefixAndLocalName[0];
+                                // the statement below causes the attribute to keep its prefix even if it is not
+                                // bound to a namespace (to support pre-namespace XML).
+                                assignedAttrPrefix = attrPrefix;
+                                attrLocalName = prefixAndLocalName[1];
+                                // note: if prefix is null, the attribute has no namespace (namespace defaulting
+                                // does not apply to attributes)
+                                if (attrPrefix != null)
+                                    attrNsURI = getNamespaceForPrefix(attrPrefix, (Element)node);
+                                else
+                                    attrNsURI = null;
+                            } else {
+                                attrLocalName = attr.getLocalName();
+                                attrPrefix = attr.getPrefix();
+                                attrNsURI = attr.getNamespaceURI();
+                            }
+
+                            if (attrNsURI != null) {
+                                String declaredUri = currentElementInfo.findNamespaceURI(attrPrefix);
+                                // if the prefix is null, or the prefix has not been declared, or conflicts with an in-scope binding
+                                if (declaredUri == null || !declaredUri.equals(attrNsURI)) {
+                                    String availablePrefix = currentElementInfo.findPrefix(attrNsURI);
+                                    if (availablePrefix != null && !availablePrefix.equals(""))
+                                        assignedAttrPrefix = availablePrefix;
+                                    else {
+                                        if (attrPrefix != null && declaredUri == null) {
+                                            // prefix is not null and is not yet declared: declare it
+                                            assignedAttrPrefix = attrPrefix;
+                                            currentElementInfo.put(assignedAttrPrefix, attrNsURI);
+                                        } else {
+                                            // attribute has no prefix (which is not allowed for namespaced attributes) or
+                                            // the prefix is already bound to something else: generate a new prefix
+                                            newPrefixCounter++;
+                                            assignedAttrPrefix = "NS" + newPrefixCounter;
+                                            currentElementInfo.put(assignedAttrPrefix, attrNsURI);
+                                        }
+                                    }
+                                } else {
+                                    assignedAttrPrefix = attrPrefix;
+                                }
+                            }
+
+                            String assignedAttrNsURI = attrNsURI != null ? attrNsURI : "";
+                            String attrQName;
+                            if (assignedAttrPrefix != null) {
+                                attrQName = assignedAttrPrefix + ":" + attrLocalName;
+                            } else {
+                                attrQName = attrLocalName;
+                            }
+                            newAttrs.addAttribute(assignedAttrNsURI, attrLocalName, attrQName, "CDATA", attr.getNodeValue());
+                        }
+                    }
+
+                    // add local namespace declaration and fire startPrefixMapping events
+                    if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) {
+                        Iterator localNsDeclIt = currentElementInfo.namespaceDeclarations.entrySet().iterator();
+                        while (localNsDeclIt.hasNext()) {
+                            Map.Entry entry = (Map.Entry) localNsDeclIt.next();
+                            String pr = (String) entry.getKey();
+                            String ns = (String) entry.getValue();
+                            // the following lines enable the creation of explicit xmlns attributes
+                            //String pr1 = pr.equals("") ? "xmlns" : pr;
+                            //String qn = pr.equals("") ? "xmlns" : "xmlns:" + pr;
+                            //newAttrs.addAttribute("", pr1, qn, "CDATA", ns);
+                            // System.out.println("starting prefix mapping  for prefix " + pr + " for " + ns);
+                            contentHandler.startPrefixMapping(pr, ns);
+                        }
+                    }
+
+                    contentHandler.startElement(namespaceURI, localName, qName, newAttrs);
+
+                    currentElementInfo.localName = localName;
+                    currentElementInfo.namespaceURI = namespaceURI;
+                    currentElementInfo.qName = qName;
+                    break;
+                case Node.PROCESSING_INSTRUCTION_NODE:
+                    {
+                        ProcessingInstruction pi = (ProcessingInstruction) node;
+                        contentHandler.processingInstruction(pi.getNodeName(), pi.getData());
+                    }
+                    break;
+                case Node.CDATA_SECTION_NODE:
+                    {
+                        if (lexicalHandler != null)
+                            lexicalHandler.startCDATA();
+
+                        dispatchChars(node);
+
+                        if (lexicalHandler != null)
+                            lexicalHandler.endCDATA();
+                    }
+                    break;
+                case Node.TEXT_NODE:
+                    {
+                        dispatchChars(node);
+                    }
+                    break;
+                case Node.ENTITY_REFERENCE_NODE:
+                    {
+                        EntityReference eref = (EntityReference) node;
+
+                        if (lexicalHandler != null) {
+                            lexicalHandler.startEntity(eref.getNodeName());
+                        } else {
+                            // warning("Can not output entity to a pure SAX ContentHandler");
+                        }
+                    }
+                    break;
+                default :
+            }
+        }
+
+        /**
+         * Searches the namespace for a given namespace prefix starting from a
+         * given Element.
+         *
+         * <p>Note that this resolves the prefix in the orginal DOM-tree, not in
+         * the {@link ElementInfo} objects. This is used to resolve prefixes
+         * of elements or attributes created with createElement or setAttribute
+         * instead of createElementNS or setAttributeNS.
+         *
+         * <p>The code in this method is largely based on
+         * org.apache.xml.utils.DOMHelper.getNamespaceForPrefix() (from Xalan).
+         *
+         * @param prefix the prefix to look for, can be empty or null to find the
+         * default namespace
+         *
+         * @return the namespace, or null if not found.
+         */
+        public String getNamespaceForPrefix(String prefix, Element namespaceContext) {
+            int type;
+            Node parent = namespaceContext;
+            String namespace = null;
+
+            if (prefix == null)
+                prefix = "";
+
+            if (prefix.equals("xml")) {
+                namespace = "http://www.w3.org/XML/1998/namespace";
+            } else if(prefix.equals("xmlns")) {
+                namespace = "http://www.w3.org/2000/xmlns/";
+            } else {
+                // Attribute name for this prefix's declaration
+                String declname = (prefix == "") ? "xmlns" : "xmlns:" + prefix;
+
+                // Scan until we run out of Elements or have resolved the namespace
+                while ((null != parent) && (null == namespace)
+                   && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
+                       || (type == Node.ENTITY_REFERENCE_NODE))) {
+                    if (type == Node.ELEMENT_NODE) {
+                        Attr attr=((Element)parent).getAttributeNode(declname);
+                        if (attr != null) {
+                            namespace = attr.getNodeValue();
+                            break;
+                        }
+                    }
+                    parent = parent.getParentNode();
+                }
+            }
+            return namespace;
+        }
+
+        /**
+         * Splits a nodeName into a prefix and a localName
+         *
+         * @return an array containing two elements, the first one is the prefix (can be null), the
+         * second one is the localName
+         */
+        private String[] getPrefixAndLocalName(String nodeName) {
+            String prefix, localName;
+            int colonPos = nodeName.indexOf(":");
+            if (colonPos != -1) {
+                prefix = nodeName.substring(0, colonPos);
+                localName = nodeName.substring(colonPos + 1, nodeName.length());
+            } else {
+                prefix = null;
+                localName = nodeName;
+            }
+            return new String[] {prefix, localName};
+        }
+
+
+        /**
+         * End processing of given node
+         *
+         * @param node Node we just finished processing
+         */
+        protected void endNode(Node node) throws org.xml.sax.SAXException {
+
+            switch (node.getNodeType()) {
+                case Node.DOCUMENT_NODE:
+                    break;
+
+                case Node.ELEMENT_NODE:
+                    contentHandler.endElement(currentElementInfo.namespaceURI,
+                            currentElementInfo.localName, currentElementInfo.qName);
+
+                    // generate endPrefixMapping events if needed
+                    if (currentElementInfo.namespaceDeclarations != null && currentElementInfo.namespaceDeclarations.size() > 0) {
+                        Iterator namespaceIt = currentElementInfo.namespaceDeclarations.entrySet().iterator();
+                        while (namespaceIt.hasNext()) {
+                            Map.Entry entry = (Map.Entry) namespaceIt.next();
+                            contentHandler.endPrefixMapping((String) entry.getKey());
+                            //System.out.println("ending prefix mapping " + (String) entry.getKey());
+                        }
+                    }
+
+                    currentElementInfo = currentElementInfo.parent;
+                    break;
+                case Node.CDATA_SECTION_NODE:
+                    break;
+                case Node.ENTITY_REFERENCE_NODE:
+                    {
+                        EntityReference eref = (EntityReference) node;
+
+                        if (lexicalHandler != null) {
+                            lexicalHandler.endEntity(eref.getNodeName());
+                        }
+                    }
+                    break;
+                default :
+            }
+        }
+
+        public static class ElementInfo {
+            public String localName;
+            public String namespaceURI;
+            public String qName;
+            public Map namespaceDeclarations = null;
+            public ElementInfo parent;
+
+            public ElementInfo(ElementInfo parent) {
+                this.parent = parent;
+            }
+
+            /**
+             * Declare a new namespace prefix on this element, possibly overriding
+             * an existing one.
+             */
+            public void put(String prefix, String namespaceURI) {
+                if (namespaceDeclarations == null)
+                    namespaceDeclarations = new HashMap();
+                namespaceDeclarations.put(prefix, namespaceURI);
+            }
+
+            /**
+             * Finds a prefix declared on this element.
+             */
+            public String getPrefix(String namespaceURI) {
+                if (namespaceDeclarations == null || namespaceDeclarations.size() == 0)
+                    return null;
+                // note: there could be more than one prefix for the same namespaceURI, but
+                // we return the first found one.
+                Iterator it = namespaceDeclarations.entrySet().iterator();
+                while (it.hasNext()) {
+                    Map.Entry entry = (Map.Entry) it.next();
+                    if (entry.getValue().equals(namespaceURI))
+                        return (String) entry.getKey();
+                }
+                return null;
+            }
+
+            /**
+             * Finds a namespace URI declared on this element.
+             */
+            public String getNamespaceURI(String prefix) {
+                if (namespaceDeclarations == null || namespaceDeclarations.size() == 0)
+                    return null;
+
+                return (String) namespaceDeclarations.get(prefix);
+            }
+
+            /**
+             * Finds a prefix declaration on this element or containing elements.
+             */
+            public String findPrefix(String namespaceURI) {
+                if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) {
+                    String prefix = getPrefix(namespaceURI);
+                    if (prefix != null) {
+                        return prefix;
+                    }
+                }
+                if (parent != null) {
+                    return parent.findPrefix(namespaceURI);
+                }
+                return null;
+            }
+
+            /**
+             * Finds a namespace declaration on this element or containing elements.
+             */
+            public String findNamespaceURI(String prefix) {
+                if (namespaceDeclarations != null && namespaceDeclarations.size() != 0) {
+                    String uri = (String) namespaceDeclarations.get(prefix);
+                    if (uri != null) {
+                        return uri;
+                    }
+                }
+                if (parent != null) {
+                    return parent.findNamespaceURI(prefix);
+                }
+                return null;
+            }
+        }
+    }
+
+    /**
+     * The <code>DefaultDOMStreamer</code> is a utility class that will generate SAX
+     * events from a W3C DOM Document.
+     *
+     * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+     * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+     *         (Apache Software Foundation)
+     */
+    public static class DefaultDOMStreamer extends AbstractXMLProducer {
+
+        /** The private transformer for this instance */
+        protected Transformer transformer;
+
+        /**
+         * Start the production of SAX events.
+         */
+        public void stream(Node node)
+        throws SAXException {
+            if (this.transformer == null) {
+                try {
+                    this.transformer = FACTORY.newTransformer();
+                } catch (TransformerConfigurationException e) {
+                    throw new SAXException(e);
+                }
+            }
+            DOMSource source = new DOMSource(node);
+
+            ContentHandler handler;
+            if (node.getNodeType() == Node.DOCUMENT_NODE) {
+                // Pass all SAX events
+                handler = contentHandler;
+            } else {
+                // Strip start/endDocument
+                handler = new EmbeddedXMLPipe(contentHandler);
+            }
+
+            SAXResult result = new SAXResult(handler);
+            result.setLexicalHandler(lexicalHandler);
+
+            try {
+                transformer.transform(source, result);
+            } catch (TransformerException e) {
+                throw new SAXException(e);
+            }
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/xml/dom/DOMStreamer.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message