| /* |
| * Copyright 2001-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.axis.utils; |
| |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.apache.axis.Constants; |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| |
| |
| /** |
| * This class is a utility to serialize a DOM node as XML. This class |
| * uses the <code>DOM Level 2</code> APIs. |
| * The main difference between this class and DOMWriter is that this class |
| * generates and prints out namespace declarations. |
| * |
| * @author Matthew J. Duftler (duftler@us.ibm.com) |
| * @author Joseph Kesselman |
| */ |
| public class DOM2Writer |
| { |
| /** |
| * Return a string containing this node serialized as XML. |
| */ |
| public static String nodeToString(Node node, boolean omitXMLDecl) |
| { |
| StringWriter sw = new StringWriter(); |
| |
| serializeAsXML(node, sw, omitXMLDecl); |
| |
| return sw.toString(); |
| } |
| |
| /** |
| * Serialize this node into the writer as XML. |
| */ |
| public static void serializeAsXML(Node node, Writer writer, |
| boolean omitXMLDecl) |
| { |
| serializeAsXML(node, writer, omitXMLDecl, false); |
| } |
| |
| /** |
| * Serialize this node into the writer as XML. |
| */ |
| public static void serializeAsXML(Node node, Writer writer, |
| boolean omitXMLDecl, |
| boolean pretty) |
| { |
| PrintWriter out = new PrintWriter(writer); |
| if (!omitXMLDecl) { |
| out.print("<?xml version=\"1.0\" encoding=\""); |
| out.print(XMLUtils.getEncoding()); |
| out.println("\"?>"); |
| } |
| NSStack namespaceStack = new NSStack(); |
| print(node, namespaceStack, node, out, pretty, 0); |
| out.flush(); |
| } |
| |
| private static void print(Node node, NSStack namespaceStack, |
| Node startnode, |
| PrintWriter out, boolean pretty, |
| int indent) |
| { |
| if (node == null) |
| { |
| return; |
| } |
| |
| boolean hasChildren = false; |
| int type = node.getNodeType(); |
| |
| switch (type) |
| { |
| case Node.DOCUMENT_NODE : |
| { |
| NodeList children = node.getChildNodes(); |
| |
| if (children != null) |
| { |
| int numChildren = children.getLength(); |
| |
| for (int i = 0; i < numChildren; i++) |
| { |
| print(children.item(i), namespaceStack, startnode, out, |
| pretty, indent); |
| } |
| } |
| break; |
| } |
| |
| case Node.ELEMENT_NODE : |
| { |
| namespaceStack.push(); |
| |
| if (pretty) { |
| for (int i = 0; i < indent; i++) |
| out.print(' '); |
| } |
| |
| out.print('<' + node.getNodeName()); |
| |
| String elPrefix = node.getPrefix(); |
| String elNamespaceURI = node.getNamespaceURI(); |
| |
| if (elPrefix != null && |
| elNamespaceURI != null && |
| elPrefix.length() > 0) |
| { |
| boolean prefixIsDeclared = false; |
| |
| try |
| { |
| String namespaceURI = namespaceStack.getNamespaceURI(elPrefix); |
| |
| if (elNamespaceURI.equals(namespaceURI)) |
| { |
| prefixIsDeclared = true; |
| } |
| } |
| catch (IllegalArgumentException e) |
| { |
| } |
| |
| if (!prefixIsDeclared) |
| { |
| printNamespaceDecl(node, namespaceStack, startnode, out); |
| } |
| } |
| |
| NamedNodeMap attrs = node.getAttributes(); |
| int len = (attrs != null) ? attrs.getLength() : 0; |
| |
| for (int i = 0; i < len; i++) |
| { |
| Attr attr = (Attr)attrs.item(i); |
| |
| out.print(' ' + attr.getNodeName() +"=\"" + |
| normalize(attr.getValue()) + '\"'); |
| |
| String attrPrefix = attr.getPrefix(); |
| String attrNamespaceURI = attr.getNamespaceURI(); |
| |
| if (attrPrefix != null && |
| attrNamespaceURI != null && |
| attrPrefix.length() > 0) |
| { |
| boolean prefixIsDeclared = false; |
| |
| try |
| { |
| String namespaceURI = namespaceStack.getNamespaceURI(attrPrefix); |
| |
| if (attrNamespaceURI.equals(namespaceURI)) |
| { |
| prefixIsDeclared = true; |
| } |
| } |
| catch (IllegalArgumentException e) |
| { |
| } |
| |
| if (!prefixIsDeclared) |
| { |
| printNamespaceDecl(attr, namespaceStack, startnode, out); |
| } |
| } |
| } |
| |
| NodeList children = node.getChildNodes(); |
| |
| if (children != null) |
| { |
| int numChildren = children.getLength(); |
| |
| hasChildren = (numChildren > 0); |
| |
| if (hasChildren) |
| { |
| out.print('>'); |
| if (pretty) |
| out.print(JavaUtils.LS); |
| } |
| |
| for (int i = 0; i < numChildren; i++) |
| { |
| print(children.item(i), namespaceStack, startnode, out, pretty, |
| indent + 1); |
| } |
| } |
| else |
| { |
| hasChildren = false; |
| } |
| |
| if (!hasChildren) |
| { |
| out.print("/>"); |
| if (pretty) |
| out.print(JavaUtils.LS); |
| } |
| |
| namespaceStack.pop(); |
| break; |
| } |
| |
| case Node.ENTITY_REFERENCE_NODE : |
| { |
| out.print('&'); |
| out.print(node.getNodeName()); |
| out.print(';'); |
| break; |
| } |
| |
| case Node.CDATA_SECTION_NODE : |
| { |
| out.print("<![CDATA["); |
| out.print(node.getNodeValue()); |
| out.print("]]>"); |
| break; |
| } |
| |
| case Node.TEXT_NODE : |
| { |
| out.print(normalize(node.getNodeValue())); |
| break; |
| } |
| |
| case Node.COMMENT_NODE : |
| { |
| out.print("<!--"); |
| out.print(node.getNodeValue()); |
| out.print("-->"); |
| if (pretty) |
| out.print(JavaUtils.LS); |
| break; |
| } |
| |
| case Node.PROCESSING_INSTRUCTION_NODE : |
| { |
| out.print("<?"); |
| out.print(node.getNodeName()); |
| |
| String data = node.getNodeValue(); |
| |
| if (data != null && data.length() > 0) |
| { |
| out.print(' '); |
| out.print(data); |
| } |
| |
| out.println("?>"); |
| if (pretty) |
| out.print(JavaUtils.LS); |
| break; |
| } |
| } |
| |
| if (type == Node.ELEMENT_NODE && hasChildren == true) |
| { |
| if (pretty) { |
| for (int i = 0; i < indent; i++) |
| out.print(' '); |
| } |
| out.print("</"); |
| out.print(node.getNodeName()); |
| out.print('>'); |
| if (pretty) |
| out.print(JavaUtils.LS); |
| hasChildren = false; |
| } |
| } |
| |
| private static void printNamespaceDecl(Node node, |
| NSStack namespaceStack, |
| Node startnode, |
| PrintWriter out) |
| { |
| switch (node.getNodeType()) |
| { |
| case Node.ATTRIBUTE_NODE : |
| { |
| printNamespaceDecl(((Attr)node).getOwnerElement(), node, |
| namespaceStack, startnode, out); |
| break; |
| } |
| |
| case Node.ELEMENT_NODE : |
| { |
| printNamespaceDecl((Element)node, node, namespaceStack, startnode, out); |
| break; |
| } |
| } |
| } |
| |
| private static void printNamespaceDecl(Element owner, Node node, |
| NSStack namespaceStack, |
| Node startnode, |
| PrintWriter out) |
| { |
| String namespaceURI = node.getNamespaceURI(); |
| String prefix = node.getPrefix(); |
| |
| if (!(namespaceURI.equals(Constants.NS_URI_XMLNS) && prefix.equals("xmlns")) && |
| !(namespaceURI.equals(Constants.NS_URI_XML) && prefix.equals("xml"))) |
| { |
| if (XMLUtils.getNamespace(prefix, owner, startnode) == null) |
| { |
| out.print(" xmlns:" + prefix + "=\"" + namespaceURI + '\"'); |
| } |
| } |
| else |
| { |
| prefix = node.getLocalName(); |
| namespaceURI = node.getNodeValue(); |
| } |
| |
| namespaceStack.add(namespaceURI, prefix); |
| } |
| |
| public static String normalize(String s) |
| { |
| return XMLUtils.xmlEncodeString(s); |
| } |
| } |