diff --git a/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElement.java b/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElement.java index 5f4bbb7..c8a7043 100644 --- a/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElement.java +++ b/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElement.java @@ -158,9 +158,26 @@ public XMLElement setChildValue(String name, String value) { * @param name the tag name of the children. * @return an {@link Iterable} of the children. */ + @SuppressWarnings("unchecked") public Iterable getChildren(String name) { // Get the child element node list + final NodeList nodes = element.getChildNodes(); + + // Build the iterators + final NodeListIterator nodeListIterator = new NodeListIterator(nodes); + return new XMLElementByTagNameIterator(name, nodeListIterator).toIterable(); + } + + /** + * Gets an {@link Iterable} for the descendants of this element by tag name. + * @param name the tag name of the descendants. + * @return an {@link Iterable} of the descendants. + */ + @SuppressWarnings("unchecked") + public Iterable getDescendants(String name) { + + // Get the descendant element node list final NodeList nodes = element.getElementsByTagName(name); // Build the iterators diff --git a/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElementByTagNameIterator.java b/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElementByTagNameIterator.java new file mode 100644 index 0000000..b6e6a0c --- /dev/null +++ b/src/main/java/com/jeffrodriguez/xmlwrapper/XMLElementByTagNameIterator.java @@ -0,0 +1,108 @@ +/* This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to + */ +package com.jeffrodriguez.xmlwrapper; + +import java.util.Iterator; + +import javax.xml.soap.Node; + +import org.w3c.dom.Element; + +/** + * An {@link Iterator} that wraps a {@link NodeListIterator} and returns only {@link XMLElement}s with a specific tag name. + * Note that any call to {@link #hasNext()} will actually retrieve the next XML node(s) in the source iterator + * until it finds an Element with the requested tag name, or until the end of the XML. + * + * @author Sorin Postelnicu + */ +public class XMLElementByTagNameIterator implements Iterator { + + /** + * The tag name to search in the source iterator. + */ + String tagName; + + /** + * The source iterator. + */ + private final NodeListIterator iterator; + + /** + * The next element that will be returned by this iterator, if exists. + */ + private XMLElement nextElement = null; + + /** + * Creates a new {@link XMLElementByTagNameIterator}. + * @param tagName the tag name to search for in the source iterator + * @param iterator the {@link NodeListIterator} to wrap. + */ + public XMLElementByTagNameIterator(String tagName, NodeListIterator iterator) { + if (tagName == null || tagName.length() == 0) { + throw new IllegalArgumentException("The tagName cannot be empty!"); + } + if (iterator == null) { + throw new IllegalArgumentException("The iterator cannot be empty!"); + } + this.tagName = tagName; + this.iterator = iterator; + } + + @Override + public boolean hasNext() { + while (iterator.hasNext()) { + Element next = iterator.next(); + if (next.getNodeType() == Node.ELEMENT_NODE + && tagName.equals(next.getNodeName())) { + nextElement = new XMLElement(next); + return true; + } + } + return false; + } + + @Override + public XMLElement next() { + return nextElement; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + /** + * @return an {@link Iterable} for this iterator. + */ + public Iterable toIterable() { + return new Iterable() { + @Override + public Iterator iterator() { + return XMLElementByTagNameIterator.this; + } + }; + } +} diff --git a/src/test/java/com/jeffrodriguez/xmlwrapper/XMLElementTest.java b/src/test/java/com/jeffrodriguez/xmlwrapper/XMLElementTest.java index 62dd44d..1b60e87 100644 --- a/src/test/java/com/jeffrodriguez/xmlwrapper/XMLElementTest.java +++ b/src/test/java/com/jeffrodriguez/xmlwrapper/XMLElementTest.java @@ -27,9 +27,9 @@ package com.jeffrodriguez.xmlwrapper; import java.util.Iterator; +import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; -import org.junit.Before; /** * @author Jeff Rodriguez @@ -45,9 +45,10 @@ public void setUp() { .addChild("bar") .setAttribute("baz", "qux"); - xml.getRoot() - .addChild("baz") - .setAttribute("qux", "true"); + XMLElement baz = xml.getRoot() + .addChild("baz"); + baz.setAttribute("qux", "true"); + baz.addChild("foobar").addChild("baz"); xml.getRoot() .addChild("baz") @@ -194,6 +195,28 @@ public void testGetChildren() { assertFalse(result.hasNext()); } + /** + * Test of getDescendants method, of class XMLElement. + */ + @Test + public void testGetDescendants() { + System.out.println("getDescendants"); + + XMLElement instance = xml.getRoot(); + Iterator result = instance.getDescendants("baz").iterator(); + + assertTrue(result.hasNext()); + assertEquals("true", result.next().getAttribute("qux")); + + assertTrue(result.hasNext()); + assertEquals("", result.next().getAttribute("qux")); + + assertTrue(result.hasNext()); + assertEquals("false", result.next().getAttribute("qux")); + + assertFalse(result.hasNext()); + } + /** * Test of hasChildren method, of class XMLElement. */