2
* The Apache Software License, Version 1.1
4
* Copyright (c) 2001 The Apache Software Foundation. All rights
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in
16
* the documentation and/or other materials provided with the
19
* 3. The end-user documentation included with the redistribution, if
20
* any, must include the following acknowlegement:
21
* "This product includes software developed by the
22
* Apache Software Foundation (http://www.apache.org/)."
23
* Alternately, this acknowlegement may appear in the software itself,
24
* if and wherever such third-party acknowlegements normally appear.
26
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
27
* Foundation" must not be used to endorse or promote products derived
28
* from this software without prior written permission. For written
29
* permission, please contact apache@apache.org.
31
* 5. Products derived from this software may not be called "Apache"
32
* nor may "Apache" appear in their names without prior written
33
* permission of the Apache Group.
35
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47
* ====================================================================
49
* This software consists of voluntary contributions made by many
50
* individuals on behalf of the Apache Software Foundation. For more
51
* information on the Apache Software Foundation, please see
52
* <http://www.apache.org/>.
54
package org.apache.tools.ant.taskdefs.optional.junit;
56
import org.w3c.dom.Node;
57
import org.w3c.dom.Document;
58
import org.w3c.dom.CDATASection;
59
import org.w3c.dom.Comment;
60
import org.w3c.dom.Element;
61
import org.w3c.dom.NamedNodeMap;
62
import org.w3c.dom.Attr;
63
import org.w3c.dom.EntityReference;
64
import org.w3c.dom.ProcessingInstruction;
65
import org.w3c.dom.Text;
66
import org.w3c.dom.NodeList;
67
import org.w3c.dom.DOMException;
69
import java.util.Vector;
72
* Some utilities that might be useful when manipulating DOM trees.
74
* @author <a href="bailliez@noos.fr">Stephane Bailliez</a>
76
public final class DOMUtil {
78
/** unused constructor */
83
* Filter interface to be applied when iterating over a DOM tree.
84
* Just think of it like a <tt>FileFilter</tt> clone.
86
public interface NodeFilter {
88
* @param node the node to check for acceptance.
89
* @return <tt>true</tt> if the node is accepted by this filter,
90
* otherwise <tt>false</tt>
92
public boolean accept(Node node);
96
* list a set of node that match a specific filter. The list can be made
98
* @param parent the parent node to search from
99
* @param filter the filter that children should match.
100
* @param recurse <tt>true</tt> if you want the list to be made recursively
101
* otherwise <tt>false</tt>.
103
public static NodeList listChildNodes(Node parent, NodeFilter filter, boolean recurse){
104
NodeListImpl matches = new NodeListImpl();
105
NodeList children = parent.getChildNodes();
106
if (children != null) {
107
final int len = children.getLength();
108
for (int i = 0; i < len; i++) {
109
Node child = children.item(i);
110
if (filter.accept(child)) {
111
matches.addElement(child);
114
NodeList recmatches = listChildNodes(child, filter, recurse);
115
final int reclength = matches.getLength();
116
for (int j = 0; j < reclength; j++) {
117
matches.addElement( recmatches.item(i) );
125
/** custom implementation of a nodelist */
126
public static class NodeListImpl extends Vector implements NodeList {
127
public int getLength(){
130
public Node item(int i){
132
return (Node)elementAt(i);
133
} catch (ArrayIndexOutOfBoundsException e){
134
return null; // conforming to NodeList interface
140
* return the attribute value of an element.
141
* @param node the node to get the attribute from.
142
* @param name the name of the attribute we are looking for the value.
143
* @return the value of the requested attribute or <tt>null</tt> if the
144
* attribute was not found or if <tt>node</tt> is not an <tt>Element</tt>.
146
public static String getNodeAttribute(Node node, String name) {
147
if (node instanceof Element) {
148
Element element = (Element)node;
149
return element.getAttribute(name);
156
* Iterate over the children of a given node and return the first node
157
* that has a specific name.
158
* @param parent the node to search child from. Can be <tt>null</tt>.
159
* @param tagname the child name we are looking for. Cannot be <tt>null</tt>.
160
* @return the first child that matches the given name or <tt>null</tt> if
161
* the parent is <tt>null</tt> or if a child does not match the
164
public static Element getChildByTagName (Node parent, String tagname) {
168
NodeList childList = parent.getChildNodes();
169
final int len = childList.getLength();
170
for (int i = 0; i < len; i++) {
171
Node child = childList.item(i);
172
if ( child != null && child.getNodeType() == Node.ELEMENT_NODE &&
173
child.getNodeName().equals(tagname)) {
174
return (Element)child;
181
* Simple tree walker that will clone recursively a node. This is to
182
* avoid using parser-specific API such as Sun's <tt>changeNodeOwner</tt>
183
* when we are dealing with DOM L1 implementations since <tt>cloneNode(boolean)</tt>
184
* will not change the owner document.
185
* <tt>changeNodeOwner</tt> is much faster and avoid the costly cloning process.
186
* <tt>importNode</tt> is in the DOM L2 interface.
187
* @param parent the node parent to which we should do the import to.
188
* @param child the node to clone recursively. Its clone will be
189
* appended to <tt>parent</tt>.
190
* @return the cloned node that is appended to <tt>parent</tt>
192
public static final Node importNode(Node parent, Node child){
194
final Document doc = parent.getOwnerDocument();
196
switch (child.getNodeType()) {
197
case Node.CDATA_SECTION_NODE:
198
copy = doc.createCDATASection(((CDATASection) child).getData());
200
case Node.COMMENT_NODE:
201
copy = doc.createComment(((Comment) child).getData());
203
case Node.DOCUMENT_FRAGMENT_NODE:
204
copy = doc.createDocumentFragment();
206
case Node.ELEMENT_NODE:
207
final Element elem = doc.createElement(((Element)child).getTagName());
209
final NamedNodeMap attributes = child.getAttributes();
210
if ( attributes != null) {
211
final int size = attributes.getLength();
212
for (int i = 0; i < size; i++) {
213
final Attr attr = (Attr) attributes.item(i);
214
elem.setAttribute(attr.getName(), attr.getValue());
218
case Node.ENTITY_REFERENCE_NODE:
219
copy = doc.createEntityReference(child.getNodeName());
221
case Node.PROCESSING_INSTRUCTION_NODE:
222
final ProcessingInstruction pi = (ProcessingInstruction)child;
223
copy = doc.createProcessingInstruction(pi.getTarget(), pi.getData());
226
copy = doc.createTextNode(((Text) child).getData());
229
// this should never happen
230
throw new IllegalStateException("Invalid node type: " + child.getNodeType());
233
// okay we have a copy of the child, now the child becomes the parent
234
// and we are iterating recursively over its children.
236
final NodeList children = child.getChildNodes();
237
if (children != null) {
238
final int size = children.getLength();
239
for (int i = 0; i < size; i++) {
240
final Node newChild = children.item(i);
241
if (newChild != null) {
242
importNode(copy, newChild);
246
} catch (DOMException ignored) {
249
// bingo append it. (this should normally not be done here)
250
parent.appendChild(copy);