1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package org.openoffice.xmerge.util;
25 
26 import org.w3c.dom.Node;
27 import org.w3c.dom.Document;
28 import org.w3c.dom.NodeList;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.NamedNodeMap;
31 
32 /**
33  *  Class containing static util methods for handling XML trees.
34  *
35  *  @author     smak
36  */
37 public final class XmlUtil {
38 
39 
40     /**
41      *  Perform a deep clone of certain <code>Node</code> which
42      *  will base on the document <code>Node</code> of the old
43      *  <code>Node</code>.
44      *
45      *  @param  oldNode  The <code>Document</code> of this
46      *                   <code>Node</code> is used to clone
47      *                   the <code>Node</code>
48      *  @param  newNode  The <code>Node</code> to clone.
49      *
50      *  @return  The cloned <code>Node</code>.
51      */
deepClone(Node oldNode, Node newNode)52     public static Node deepClone(Node oldNode, Node newNode) {
53         Document docNode = oldNode.getOwnerDocument();
54 
55         // clone the starting node
56         Node clonedNode = cloneNode(docNode, newNode);
57 
58         // then clone the sub-tree recursively
59         cloneTree(docNode, clonedNode, newNode);
60 
61         return clonedNode;
62     }
63 
64 
65     /**
66      *  Clone the sub-tree under certain given <code>Node</code>
67      *
68      *  @param  docNode  The <code>Document</code> used to clone
69      *                   the <code>Node</code>.
70      *  @param  oldNode  The <code>Node</code> to clone.
71      *  @param  newNode  The destination <code>Node</code>.
72      */
cloneTree(Document docNode, Node oldNode, Node newNode)73     private static void cloneTree(Document docNode, Node oldNode, Node newNode) {
74 
75         NodeList nodeList = newNode.getChildNodes();
76         int nodeListLen = nodeList.getLength();
77 
78         for (int i = 0; i < nodeListLen; i++) {
79             Node newClonedChild = cloneNode(docNode, nodeList.item(i));
80             if (newClonedChild != null) {
81                 oldNode.appendChild(newClonedChild);
82                 cloneTree(docNode, newClonedChild, nodeList.item(i));
83             }
84         }
85     }
86 
87 
88     /**
89      * Clone a <code>Node</code> (either text or element).
90      *
91      * @param  docNode  The <code>Document</code> used to
92      *                  clone the <code>Node</code>.
93      * @param  newNode  The <code>Node</code> to clone.
94      *
95      * @return  The cloned <code>Node</code>.
96      */
cloneNode(Document docNode, Node newNode)97     private static Node cloneNode(Document docNode, Node newNode) {
98 
99         Node clonedNode = null;
100 
101         // only support text node and element node (will copy the attributes)
102         switch (newNode.getNodeType()) {
103             case Node.TEXT_NODE:
104                 String textStr = newNode.getNodeValue();
105                 clonedNode = docNode.createTextNode(textStr);
106                 break;
107             case Node.ELEMENT_NODE:
108                 Element oldElem = (Element)newNode;
109                 String tagName  = newNode.getNodeName();
110                 Element newElem = (docNode.createElement(tagName));
111 
112                 // copy the attributes
113                 NamedNodeMap attrs = oldElem.getAttributes();
114 
115                 for (int i = 0; i < attrs.getLength(); i++) {
116                     newElem.setAttribute(attrs.item(i).getNodeName(),
117                                          attrs.item(i).getNodeValue());
118                 }
119                 clonedNode = newElem;
120                 break;
121         }
122         return clonedNode;
123     }
124 
125 
126     /**
127      *  Returns the name and type of an XML DOM <code>Node</code>.
128      *
129      *  @param  node  <code>Node</code> to query.
130      *
131      *  @return  Name and type of XML DOM <code>Node</code>.
132      */
getNodeInfo(Node node)133     public static String getNodeInfo(Node node) {
134 
135         String str = null;
136         switch (node.getNodeType()) {
137 
138         	case Node.ELEMENT_NODE:
139         	    str = "ELEMENT";
140         	    break;
141         	case Node.ATTRIBUTE_NODE:
142         	    str = "ATTRIBUTE";
143         	    break;
144         	case Node.TEXT_NODE:
145         	    str = "TEXT";
146         	    break;
147         	case Node.CDATA_SECTION_NODE:
148         	    str = "CDATA_SECTION";
149         	    break;
150         	case Node.ENTITY_REFERENCE_NODE:
151         	    str = "ENTITY_REFERENCE";
152         	    break;
153         	case Node.ENTITY_NODE:
154         	    str = "ENTITY";
155         	    break;
156         	case Node.PROCESSING_INSTRUCTION_NODE:
157         	    str = "PROCESSING_INSTRUCTION";
158         	    break;
159         	case Node.COMMENT_NODE:
160         	    str = "COMMENT";
161         	    break;
162         	case Node.DOCUMENT_NODE:
163         	    str = "DOCUMENT";
164         	    break;
165         	case Node.DOCUMENT_TYPE_NODE:
166         	    str = "DOCUMENT_TYPE";
167         	    break;
168         	case Node.DOCUMENT_FRAGMENT_NODE:
169         	    str = "DOCUMENT_FRAGMENT";
170         	    break;
171         	case Node.NOTATION_NODE:
172         	    str = "NOTATION";
173         	    break;
174         }
175 
176         StringBuffer buffer = new StringBuffer("name=\"");
177         buffer.append(node.getNodeName());
178         buffer.append("\"  type=\"");
179         buffer.append(str);
180         buffer.append("\"");
181 
182         return buffer.toString();
183     }
184 }
185 
186