Package org.apache.ws.commons.serialize

Source Code of org.apache.ws.commons.serialize.DOMSerializer

/*
* Copyright 2003, 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.ws.commons.serialize;

import javax.xml.XMLConstants;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;

/** Serializes a DOM node into a stream of SAX events.
*/
public class DOMSerializer {
  private boolean namespaceDeclarationAttribute;
  private boolean parentsNamespaceDeclarationDisabled;
  private boolean startingDocument = true;
 
  /** Sets whether XML namespace declarations are being serialized as
   * attributes or as SAX events (default).
   * @param pXmlDeclarationAttribute True, if a namespace declaration
   * is being transmitted as an XML attribute. False otherwise.
   */
  public void setNamespaceDeclarationAttribute(boolean pXmlDeclarationAttribute) {
    namespaceDeclarationAttribute = pXmlDeclarationAttribute;
  }
 
  /** Returns whether XML declarations are being serialized as
   * attributes or as SAX events (default).
   * @return True, if a namespace declaration
   * is being transmitted as an XML attribute. False otherwise.
   */
  public boolean isNamespaceDeclarationAttribute() {
    return namespaceDeclarationAttribute;
  }
 
  /** Returns whether XML declarations present in the parent nodes
   * are being serialized (default) or not. This option takes effect
   * only if the namespace declarations are sent as events. In other
   * words, if the <code>namespaceDeclarationAttribute</code>
   * properts is false.
   * @param pParentsXmlDeclarationDisabled True, if namespace
   * declarations of the parent nodes are disabled, false otherwise.
   */
  public void setParentsNamespaceDeclarationDisabled(boolean pParentsXmlDeclarationDisabled) {
    parentsNamespaceDeclarationDisabled = pParentsXmlDeclarationDisabled;
  }
 
  /** Sets whether XML declarations present in the parent nodes
   * are being serialized (default) or not. This option takes effect
   * only if the namespace declarations are sent as events. In other
   * words, if the <code>namespaceDeclarationAttribute</code>
   * properts is false.
   * @return True, if namespace declarations of the parent nodes are
   * disabled, false otherwise.
   */
  public boolean isParentsNamespaceDeclarationDisabled() {
    return parentsNamespaceDeclarationDisabled;
  }

  /** Returns, whether <code>startDocument</code> and
   * <code>endDocument</code> events are generated for
   * document nodes.
   * @return True (default), if <code>startDocument</code> and
   * <code>endDocument</code> events are being generated.
   * False otherwise.
   */
  public boolean isStartingDocument() {
    return startingDocument;
  }

  /** Sets, whether <code>startDocument</code> and
   * <code>endDocument</code> events are generated for
   * document nodes.
   * @param pStartingDocument True (default), if
   * <code>startDocument</code> and
   * <code>endDocument</code> events are being generated.
   * False otherwise.
   */
  public void setStartingDocument(boolean pStartingDocument) {
    startingDocument = pStartingDocument;
  }

  /** Serializes the childs of <code>pNode</code>.
   * @param pNode The parent node, whose childs are being serialized.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  protected void doSerializeChilds(Node pNode, ContentHandler pHandler)
      throws SAXException {
    for (Node child = pNode.getFirstChild();  child != null;
    child = child.getNextSibling()) {
      doSerialize(child, pHandler);
    }
  }

  /** Initially creates startPrefixMapping events for the nodes parents. This
   * is invoked only, if {@link #isNamespaceDeclarationAttribute()},
   * and {@link #isParentsNamespaceDeclarationDisabled()} are false.
   * @param pNode The node, for which namespace declarations are being
   * created.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  private void parentsStartPrefixMappingEvents(Node pNode, ContentHandler pHandler)
      throws SAXException {
    if (pNode != null) {
      parentsStartPrefixMappingEvents(pNode.getParentNode(), pHandler);
      if (pNode.getNodeType() == Node.ELEMENT_NODE) {
        startPrefixMappingEvents(pNode, pHandler);
      }
    }
  }

  /** Finally creates endPrefixMapping events for the nodes parents. This
   * is invoked only, if {@link #isNamespaceDeclarationAttribute()},
   * and {@link #isParentsNamespaceDeclarationDisabled()} are false.
   * @param pNode The node, for which namespace declarations are being
   * created.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  private void parentsEndPrefixMappingEvents(Node pNode, ContentHandler pHandler)
      throws SAXException {
    if (pNode != null) {
      if (pNode.getNodeType() == Node.ELEMENT_NODE) {
        endPrefixMappingEvents(pNode, pHandler);
      }
      parentsEndPrefixMappingEvents(pNode.getParentNode(), pHandler);
    }
  }

  /** Creates startPrefixMapping events for the node <code>pNode</code>.
   * @param pNode The node being serialized.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  private void startPrefixMappingEvents(Node pNode, ContentHandler pHandler)
      throws SAXException {
    NamedNodeMap nnm = pNode.getAttributes();
    if (nnm != null) {
      for (int i = 0;  i < nnm.getLength();  i++) {
        Node attr = nnm.item(i);
        if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) {
          String prefix;
          if (XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getPrefix())) {
            prefix = attr.getLocalName();
          } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(attr.getNodeName())) {
            prefix = "";
          } else {
            throw new IllegalStateException("Unable to parse namespace declaration: " + attr.getNodeName());
          }
          String uri = attr.getNodeValue();
          if (uri == null) {
            uri = "";
          }
          pHandler.startPrefixMapping(prefix, uri);
        }
      }
    }
  }
 
  /** Creates endPrefixMapping events for the node <code>pNode</code>.
   * @param pNode The node being serialized.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  private void endPrefixMappingEvents(Node pNode, ContentHandler pHandler)
      throws SAXException {
    NamedNodeMap nnm = pNode.getAttributes();
    if (nnm != null) {
      for (int i = nnm.getLength()-1;  i >= 0;  i--) {
        Node attr = nnm.item(i);
        if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) {
          String prefix = attr.getLocalName();
          pHandler.endPrefixMapping(prefix);
        }
      }
    }
  }

  private void characters(ContentHandler pHandler, String pValue, boolean pCdata)
      throws SAXException {
    LexicalHandler lh;
    if (pCdata) {
      lh = (pHandler instanceof LexicalHandler) ? (LexicalHandler) pHandler : null;
    } else {
      lh = null;
    }
    if (lh != null) {
      lh.startCDATA();
    }
    pHandler.characters(pValue.toCharArray(), 0, pValue.length());
    if (lh != null) {
      lh.endCDATA();
    }
  }

  /** Converts the given node <code>pNode</code> into a
   * stream of SAX events, which are fired into the
   * content handler <code>pHandler</code>.
   * @param pNode The node being serialized.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  public void serialize(Node pNode, ContentHandler pHandler)
      throws SAXException {
    if (!isNamespaceDeclarationAttribute()  &&
        !isParentsNamespaceDeclarationDisabled()) {
      parentsStartPrefixMappingEvents(pNode.getParentNode(), pHandler);
    }
    doSerialize(pNode, pHandler);
    if (!isNamespaceDeclarationAttribute()  &&
        !isParentsNamespaceDeclarationDisabled()) {
      parentsEndPrefixMappingEvents(pNode.getParentNode(), pHandler);
    }
  }

  /** Converts the given node <code>pNode</code> into a
   * stream of SAX events, which are fired into the
   * content handler <code>pHandler</code>. Unlike
   * {@link #serialize(Node, ContentHandler)}, this method
   * doesn't call
   * {@link #parentsStartPrefixMappingEvents(Node, ContentHandler)},
   * and
   * {@link #parentsEndPrefixMappingEvents(Node, ContentHandler)}.
   * @param pNode The node being serialized.
   * @param pHandler The target handler.
   * @throws SAXException The target handler reported an error.
   */
  protected void doSerialize(Node pNode, ContentHandler pHandler)
      throws SAXException {
    switch (pNode.getNodeType()) {
      case Node.DOCUMENT_NODE:
        boolean startDocumentEvent = isStartingDocument();
        if (startDocumentEvent) {
          pHandler.startDocument();
        }
        doSerializeChilds(pNode, pHandler);
        if (startDocumentEvent) {
          pHandler.endDocument();
        }
        break;
      case Node.DOCUMENT_FRAGMENT_NODE:
        doSerializeChilds(pNode, pHandler);
        break;
      case Node.ELEMENT_NODE:
        AttributesImpl attr = new AttributesImpl();
        boolean isNamespaceDeclarationAttribute = isNamespaceDeclarationAttribute();
        if (!isNamespaceDeclarationAttribute) {
          startPrefixMappingEvents(pNode, pHandler);
        }
        NamedNodeMap nnm = pNode.getAttributes();
        if (nnm != null) {
          for (int i = 0;  i < nnm.getLength();  i++) {
            Node a = nnm.item(i);
            if (isNamespaceDeclarationAttribute  ||
                !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(a.getNamespaceURI())) {
              String aUri = a.getNamespaceURI();
              String aLocalName = a.getLocalName();
              String aNodeName = a.getNodeName();
              if (aLocalName == null) {
                if (aUri == null  ||  aUri.length() == 0) {
                  aLocalName = aNodeName;
                } else {
                  throw new IllegalStateException("aLocalName is null");
                }
              }
              //  uri The Namespace URI, or the empty string if none is available or Namespace processing is not being performed.
              //  localName The local name, or the empty string if Namespace processing is not being performed.
              //  qName The qualified (prefixed) name, or the empty string if qualified names are not available.
              //  type The attribute type as a string.
              //  value The attribute value             
              attr.addAttribute(aUri == null ? "" : aUri,
                  aLocalName, aNodeName,  // JBH 2013 05 17 these args were the wrong way around!
                   "CDATA", a.getNodeValue());
//              attr.addAttribute(aUri == null ? "" : aUri,
//                  aNodeName,
//                  aLocalName, "CDATA", a.getNodeValue());
            }
          }
        }
        String nUri = pNode.getNamespaceURI();
        if (nUri == null) {
          nUri = "";
        }
        pHandler.startElement(nUri, pNode.getLocalName(),
            pNode.getNodeName(), attr);
        doSerializeChilds(pNode, pHandler);
        pHandler.endElement(nUri, pNode.getLocalName(),
            pNode.getNodeName());
        if (!isNamespaceDeclarationAttribute) {
          endPrefixMappingEvents(pNode, pHandler);
        }
        break;
      case Node.TEXT_NODE:
        characters(pHandler, pNode.getNodeValue(), false);
        break;
      case Node.CDATA_SECTION_NODE:
        characters(pHandler, pNode.getNodeValue(), true);
        break;
      case Node.PROCESSING_INSTRUCTION_NODE:
        pHandler.processingInstruction(pNode.getNodeName(), pNode.getNodeValue());
        break;
      case Node.ENTITY_REFERENCE_NODE:
        pHandler.skippedEntity(pNode.getNodeName());
        break;
      case Node.COMMENT_NODE:
        if (pHandler instanceof LexicalHandler) {
          String s = pNode.getNodeValue();
          ((LexicalHandler) pHandler).comment(s.toCharArray(), 0, s.length());
        }
        break;
      default:
        throw new IllegalStateException("Unknown node type: " + pNode.getNodeType());
    }
  }
}
TOP

Related Classes of org.apache.ws.commons.serialize.DOMSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.