| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.openoffice.xmerge.util; |
| |
| import org.w3c.dom.Node; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| |
| /** |
| * Class containing static util methods for handling XML trees. |
| * |
| * @author smak |
| */ |
| public final class XmlUtil { |
| |
| |
| /** |
| * Perform a deep clone of certain <code>Node</code> which |
| * will base on the document <code>Node</code> of the old |
| * <code>Node</code>. |
| * |
| * @param oldNode The <code>Document</code> of this |
| * <code>Node</code> is used to clone |
| * the <code>Node</code> |
| * @param newNode The <code>Node</code> to clone. |
| * |
| * @return The cloned <code>Node</code>. |
| */ |
| public static Node deepClone(Node oldNode, Node newNode) { |
| Document docNode = oldNode.getOwnerDocument(); |
| |
| // clone the starting node |
| Node clonedNode = cloneNode(docNode, newNode); |
| |
| // then clone the sub-tree recursively |
| cloneTree(docNode, clonedNode, newNode); |
| |
| return clonedNode; |
| } |
| |
| |
| /** |
| * Clone the sub-tree under certain given <code>Node</code> |
| * |
| * @param docNode The <code>Document</code> used to clone |
| * the <code>Node</code>. |
| * @param oldNode The <code>Node</code> to clone. |
| * @param newNode The destination <code>Node</code>. |
| */ |
| private static void cloneTree(Document docNode, Node oldNode, Node newNode) { |
| |
| NodeList nodeList = newNode.getChildNodes(); |
| int nodeListLen = nodeList.getLength(); |
| |
| for (int i = 0; i < nodeListLen; i++) { |
| Node newClonedChild = cloneNode(docNode, nodeList.item(i)); |
| if (newClonedChild != null) { |
| oldNode.appendChild(newClonedChild); |
| cloneTree(docNode, newClonedChild, nodeList.item(i)); |
| } |
| } |
| } |
| |
| |
| /** |
| * Clone a <code>Node</code> (either text or element). |
| * |
| * @param docNode The <code>Document</code> used to |
| * clone the <code>Node</code>. |
| * @param newNode The <code>Node</code> to clone. |
| * |
| * @return The cloned <code>Node</code>. |
| */ |
| private static Node cloneNode(Document docNode, Node newNode) { |
| |
| Node clonedNode = null; |
| |
| // only support text node and element node (will copy the attributes) |
| switch (newNode.getNodeType()) { |
| case Node.TEXT_NODE: |
| String textStr = newNode.getNodeValue(); |
| clonedNode = docNode.createTextNode(textStr); |
| break; |
| case Node.ELEMENT_NODE: |
| Element oldElem = (Element)newNode; |
| String tagName = newNode.getNodeName(); |
| Element newElem = (docNode.createElement(tagName)); |
| |
| // copy the attributes |
| NamedNodeMap attrs = oldElem.getAttributes(); |
| |
| for (int i = 0; i < attrs.getLength(); i++) { |
| newElem.setAttribute(attrs.item(i).getNodeName(), |
| attrs.item(i).getNodeValue()); |
| } |
| clonedNode = newElem; |
| break; |
| } |
| return clonedNode; |
| } |
| |
| |
| /** |
| * Returns the name and type of an XML DOM <code>Node</code>. |
| * |
| * @param node <code>Node</code> to query. |
| * |
| * @return Name and type of XML DOM <code>Node</code>. |
| */ |
| public static String getNodeInfo(Node node) { |
| |
| String str = null; |
| switch (node.getNodeType()) { |
| |
| case Node.ELEMENT_NODE: |
| str = "ELEMENT"; |
| break; |
| case Node.ATTRIBUTE_NODE: |
| str = "ATTRIBUTE"; |
| break; |
| case Node.TEXT_NODE: |
| str = "TEXT"; |
| break; |
| case Node.CDATA_SECTION_NODE: |
| str = "CDATA_SECTION"; |
| break; |
| case Node.ENTITY_REFERENCE_NODE: |
| str = "ENTITY_REFERENCE"; |
| break; |
| case Node.ENTITY_NODE: |
| str = "ENTITY"; |
| break; |
| case Node.PROCESSING_INSTRUCTION_NODE: |
| str = "PROCESSING_INSTRUCTION"; |
| break; |
| case Node.COMMENT_NODE: |
| str = "COMMENT"; |
| break; |
| case Node.DOCUMENT_NODE: |
| str = "DOCUMENT"; |
| break; |
| case Node.DOCUMENT_TYPE_NODE: |
| str = "DOCUMENT_TYPE"; |
| break; |
| case Node.DOCUMENT_FRAGMENT_NODE: |
| str = "DOCUMENT_FRAGMENT"; |
| break; |
| case Node.NOTATION_NODE: |
| str = "NOTATION"; |
| break; |
| } |
| |
| StringBuffer buffer = new StringBuffer("name=\""); |
| buffer.append(node.getNodeName()); |
| buffer.append("\" type=\""); |
| buffer.append(str); |
| buffer.append("\""); |
| |
| return buffer.toString(); |
| } |
| } |
| |