Author: veithen Date: Sun Dec 14 16:32:37 2008 New Revision: 726587 URL: http://svn.apache.org/viewvc?rev=726587&view=rev Log: Fixed multiple bugs in ElementImpl#getElementsByTagName and ElementImpl#getElementsByTagNameNS, in particular the fact that they only considered direct children, not all descendants (WSCOMMONS-255).
To this end: * Added a couple of new test cases to ElementImplTest. * Added new iterator implementations to axiom-api that are able to iterate over descendants in document order. * Turned NodeListImpl into an abstract class (with an abstract getIterator method) which is now implemented by anonymous classes in ParentNode#getChildNodes, ElementImpl#getElementsByTagName and ElementImpl#getElementsByTagNameNS. This makes the code easier to maintain. Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java (with props) Modified: webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ElementImpl.java webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/NodeListImpl.java webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ParentNode.java webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/dom/ElementImplTest.java Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java?rev=726587&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java Sun Dec 14 16:32:37 2008 @@ -0,0 +1,77 @@ +/* + * 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.apache.axiom.om.impl.traverse; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.apache.axiom.om.OMNode; + +/** + * Abstract base class for iterators over sets of OM nodes. + */ +// TODO: We should implement remove and use this as base class for OMChildrenIterator +public abstract class OMAbstractIterator implements Iterator { + private OMNode currentNode; + private OMNode nextNode; + private boolean noMoreNodes; + + public OMAbstractIterator(OMNode firstNode) { + if (firstNode == null) { + noMoreNodes = true; + } else { + nextNode = firstNode; + } + } + + /** + * Get the next node. + * + * @param currentNode the predecessor of the node to retrieve + * @return the next node + */ + protected abstract OMNode getNextNode(OMNode currentNode); + + public boolean hasNext() { + if (noMoreNodes) { + return false; + } else if (nextNode != null) { + return true; + } else { + nextNode = getNextNode(currentNode); + noMoreNodes = nextNode == null; + return !noMoreNodes; + } + } + + public Object next() { + if (hasNext()) { + currentNode = nextNode; + nextNode = null; + return currentNode; + } else { + throw new NoSuchElementException(); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMAbstractIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java?rev=726587&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java Sun Dec 14 16:32:37 2008 @@ -0,0 +1,56 @@ +/* + * 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.apache.axiom.om.impl.traverse; + +import org.apache.axiom.om.OMContainer; +import org.apache.axiom.om.OMNode; + +/** + * Iterator that iterates over all descendants in document order. + */ +public class OMDescendantsIterator extends OMAbstractIterator { + private int level; + + public OMDescendantsIterator(OMNode firstNode) { + super(firstNode); + } + + protected OMNode getNextNode(OMNode currentNode) { + if (currentNode instanceof OMContainer) { + OMNode firstChild = ((OMContainer)currentNode).getFirstOMChild(); + if (firstChild != null) { + level++; + return firstChild; + } + } + OMNode node = currentNode; + while (true) { + OMNode nextSibling = node.getNextOMSibling(); + if (nextSibling != null) { + return nextSibling; + } else if (level == 0) { + return null; + } else { + node = (OMNode)node.getParent(); + level--; + } + } + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMDescendantsIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java?rev=726587&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java Sun Dec 14 16:32:37 2008 @@ -0,0 +1,80 @@ +/* + * 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.apache.axiom.om.impl.traverse; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.apache.axiom.om.OMNode; + +/** + * Abstract iterator that returns matching nodes from another iterator. + */ +// TODO: We should use this as base class for the OMChildrenXxxIterator classes +public abstract class OMFilterIterator implements Iterator { + private final Iterator parent; + private OMNode nextNode; + private boolean noMoreNodes; + + public OMFilterIterator(Iterator parent) { + this.parent = parent; + } + + /** + * Determine whether the given node matches the filter criteria. + * + * @param node the node to test + * @return true if the node matches, i.e. if it should be returned + * by a call to {...@link #next()} + */ + protected abstract boolean matches(OMNode node); + + public boolean hasNext() { + if (noMoreNodes) { + return false; + } else if (nextNode != null) { + return true; + } else { + while (parent.hasNext()) { + OMNode node = (OMNode)parent.next(); + if (matches(node)) { + nextNode = node; + return true; + } + } + noMoreNodes = true; + return false; + } + } + + public Object next() { + if (hasNext()) { + OMNode result = nextNode; + nextNode = null; + return result; + } else { + throw new NoSuchElementException(); + } + } + + public void remove() { + parent.remove(); + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMFilterIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java?rev=726587&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java Sun Dec 14 16:32:37 2008 @@ -0,0 +1,45 @@ +/* + * 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.apache.axiom.om.impl.traverse; + +import java.util.Iterator; + +import javax.xml.namespace.QName; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMNode; + +/** + * Iterator that selects elements based on {...@link QName} equality, + * i.e. namespace URI and local name. + * Namespace prefixes are not taken into account by the filter. + */ +public class OMQNameFilterIterator extends OMFilterIterator { + private final QName qname; + + public OMQNameFilterIterator(Iterator parent, QName qname) { + super(parent); + this.qname = qname; + } + + protected boolean matches(OMNode node) { + return node instanceof OMElement && ((OMElement)node).getQName().equals(qname); + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQNameFilterIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java?rev=726587&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java Sun Dec 14 16:32:37 2008 @@ -0,0 +1,65 @@ +/* + * 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.apache.axiom.om.impl.traverse; + +import java.util.Iterator; + +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMNamespace; +import org.apache.axiom.om.OMNode; + +/** + * Iterator that selects elements based on prefix and local name. + * Note that namespace URIs are not taken into account by the filter. + */ +public class OMQualifiedNameFilterIterator extends OMFilterIterator { + private final String prefix; + private final String localName; + + public OMQualifiedNameFilterIterator(Iterator parent, String qualifiedName) { + super(parent); + int idx = qualifiedName.indexOf(':'); + if (idx == -1) { + prefix = null; + localName = qualifiedName; + } else { + prefix = qualifiedName.substring(0, idx); + localName = qualifiedName.substring(idx+1); + } + } + + protected boolean matches(OMNode node) { + if (node instanceof OMElement) { + OMElement element = (OMElement)node; + if (!localName.equals(element.getLocalName())) { + return false; + } else { + OMNamespace ns = ((OMElement)node).getNamespace(); + if (prefix == null) { + return ns == null || ns.getPrefix().length() == 0; + } else { + return ns != null && prefix.equals(ns.getPrefix()); + } + } + } else { + return false; + } + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/traverse/OMQualifiedNameFilterIterator.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ElementImpl.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ElementImpl.java?rev=726587&r1=726586&r2=726587&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ElementImpl.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ElementImpl.java Sun Dec 14 16:32:37 2008 @@ -32,6 +32,9 @@ import org.apache.axiom.om.impl.OMNodeEx; import org.apache.axiom.om.impl.dom.factory.OMDOMFactory; import org.apache.axiom.om.impl.traverse.OMChildElementIterator; +import org.apache.axiom.om.impl.traverse.OMDescendantsIterator; +import org.apache.axiom.om.impl.traverse.OMQNameFilterIterator; +import org.apache.axiom.om.impl.traverse.OMQualifiedNameFilterIterator; import org.apache.axiom.om.impl.util.EmptyIterator; import org.apache.axiom.om.impl.util.OMSerializerUtil; import org.apache.axiom.om.util.ElementHelper; @@ -628,7 +631,13 @@ */ public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { - return new NodeListImpl(this, namespaceURI, localName); + final QName qname = new QName(namespaceURI, localName); + return new NodeListImpl() { + protected Iterator getIterator() { + return new OMQNameFilterIterator( + new OMDescendantsIterator(getFirstOMChild()), qname); + } + }; } /* @@ -636,8 +645,21 @@ * * @see org.w3c.dom.Element#getElementsByTagName(java.lang.String) */ - public NodeList getElementsByTagName(String name) { - return new NodeListImpl(this, name); + public NodeList getElementsByTagName(final String name) { + if (name.equals("*")) { + return new NodeListImpl() { + protected Iterator getIterator() { + return new OMDescendantsIterator(getFirstOMChild()); + } + }; + } else { + return new NodeListImpl() { + protected Iterator getIterator() { + return new OMQualifiedNameFilterIterator( + new OMDescendantsIterator(getFirstOMChild()), name); + } + }; + } } // / Modified: webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/NodeListImpl.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/NodeListImpl.java?rev=726587&r1=726586&r2=726587&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/NodeListImpl.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/NodeListImpl.java Sun Dec 14 16:32:37 2008 @@ -19,66 +19,14 @@ package org.apache.axiom.om.impl.dom; -import org.apache.axiom.om.impl.OMContainerEx; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import javax.xml.namespace.QName; import java.util.Iterator; -import java.util.Vector; /** Implementation of org.w3c.dom.NodeList */ -public class NodeListImpl implements NodeList { - - protected NodeImpl rootNode; - - protected String tagName; - - protected Vector nodes; - - protected String nsName; - - protected boolean enableNS = false; - - /** Constructor. */ - public NodeListImpl(NodeImpl rootNode, String tagName) { - this.rootNode = rootNode; - this.tagName = (tagName != null && !tagName.equals("")) ? tagName - : null; - nodes = new Vector(); - } - - /** Constructor for Namespace support. */ - public NodeListImpl(NodeImpl rootNode, String namespaceURI, - String localName) { - this(rootNode, localName); - this.nsName = (namespaceURI != null && !namespaceURI.equals("")) - ? namespaceURI - : null; - if (this.nsName != null) { - enableNS = true; - } - } - - private Iterator getIterator() { - if (this.tagName == null) { - return ((OMContainerEx) rootNode).getChildren(); - } else if (!enableNS) { - return ((OMContainerEx) rootNode) - .getChildrenWithName(new QName(this.tagName)); - } else { - if (DOMUtil.getPrefix(this.tagName) != null) { - return ((OMContainerEx) rootNode) - .getChildrenWithName(new QName(this.nsName, DOMUtil - .getLocalName(this.tagName), DOMUtil - .getPrefix(this.tagName))); - } else { - return ((OMContainerEx) rootNode) - .getChildrenWithName(new QName(this.nsName, DOMUtil - .getLocalName(this.tagName))); - } - } - } +public abstract class NodeListImpl implements NodeList { + protected abstract Iterator getIterator(); /** * Returns the number of nodes. Modified: webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ParentNode.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ParentNode.java?rev=726587&r1=726586&r2=726587&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ParentNode.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-dom/src/main/java/org/apache/axiom/om/impl/dom/ParentNode.java Sun Dec 14 16:32:37 2008 @@ -20,7 +20,6 @@ package org.apache.axiom.om.impl.dom; import org.apache.axiom.om.OMComment; -import org.apache.axiom.om.OMContainer; import org.apache.axiom.om.OMDocType; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMException; @@ -157,7 +156,11 @@ if (!this.done) { this.build(); } - return new NodeListImpl(this, null, null); + return new NodeListImpl() { + protected Iterator getIterator() { + return getChildren(); + } + }; } public Node getFirstChild() { Modified: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/dom/ElementImplTest.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/dom/ElementImplTest.java?rev=726587&r1=726586&r2=726587&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/dom/ElementImplTest.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/om/impl/dom/ElementImplTest.java Sun Dec 14 16:32:37 2008 @@ -19,11 +19,10 @@ package org.apache.axiom.om.impl.dom; -import junit.framework.TestCase; +import org.apache.axiom.om.AbstractTestCase; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMText; import org.apache.axiom.om.impl.dom.factory.OMDOMFactory; -import org.apache.axiom.om.impl.dom.jaxp.DOOMDocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -35,7 +34,7 @@ import java.io.ByteArrayOutputStream; import java.util.Iterator; -public class ElementImplTest extends TestCase { +public class ElementImplTest extends AbstractTestCase { public void testSetText() { OMDOMFactory factory = new OMDOMFactory(); String localName = "TestLocalName"; @@ -125,7 +124,7 @@ } /** Testing the NodeList returned with the elements's children */ - public void testGetElementsbyTagName() throws Exception { + public void testGetElementsByTagName() throws Exception { DOMTestUtil.execute(new DOMTestUtil.Test() { public void execute(DocumentBuilderFactory dbf) throws Exception { String childElementLN = "Child"; @@ -150,7 +149,34 @@ }); } - public void testGetElementsbyTagNameNS() throws Exception { + public void testGetElementsByTagNameWithNamespaces() throws Exception { + DOMTestUtil.execute(new DOMTestUtil.Test() { + public void execute(DocumentBuilderFactory dbf) throws Exception { + Document doc = dbf.newDocumentBuilder().newDocument(); + Element root = doc.createElementNS("urn:ns1", "ns1:root"); + for (int i=0; i<3; i++) { + root.appendChild(doc.createElementNS("urn:ns2", "ns2:child")); + } + assertEquals(3, root.getElementsByTagName("ns2:child").getLength()); + assertEquals(0, root.getElementsByTagName("child").getLength()); + } + }); + } + + public void testGetElementsByTagNameWithWildcard() throws Exception { + DOMTestUtil.execute(new DOMTestUtil.Test() { + public void execute(DocumentBuilderFactory dbf) throws Exception { + Document doc = dbf.newDocumentBuilder().newDocument(); + Element root = doc.createElement("root"); + for (int i=0; i<3; i++) { + root.appendChild(doc.createElement("child" + i)); + } + assertEquals(3, root.getElementsByTagName("*").getLength()); + } + }); + } + + public void testGetElementsByTagNameNS() throws Exception { DOMTestUtil.execute(new DOMTestUtil.Test() { public void execute(DocumentBuilderFactory dbf) throws Exception { String childElementQN = "test:Child"; @@ -177,4 +203,16 @@ } }); } + + public void testGetElementsByTagNameRecursive() throws Exception { + DOMTestUtil.execute(new DOMTestUtil.Test() { + public void execute(DocumentBuilderFactory dbf) throws Exception { + Document doc = + dbf.newDocumentBuilder().parse(getTestResourceFile("xml/numbers.xml")); + Element element = doc.getDocumentElement(); + NodeList list = element.getElementsByTagName("nr"); + assertEquals(10, list.getLength()); + } + }); + } }