Iterating a NodeList consisting some tags with same name using DOM
13,545
Solution 1
((Node) foodNode.getChildNodes().item(0)).getNodeValue()
Note that, as you can clearly see, dealing with the DOM API in Java is pretty painful. Have you looked at JDOM or dom4j?
Solution 2
To get the sub elements of an element I've created a class that replace NodeList:
ElementList as Replacement for NodeList
Note that the code is public domain.
/*
* The code of this file is in public domain.
*/
package org.xins.common.xml;
import Java.util.LinkedList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xins.common.text.ParseException;
/**
* An ElementList is an NodeList with the following improvements:
*
Implements List which make it iterable with for each loop *
Only includes the direct child of the element *
Only includes the elements *
By default includes all direct child elements *
Preserves the order of the child elements *
Includes a method to get the sub element when unique *
*
* @author Anthony Goubard
*
* @since XINS 3.0
*/
public class ElementList extends LinkedList {
/**
* The local name of the parent element.
*/
private String parentName;
/**
* The local name of the child elements or * for all elements
*/
private String childName;
/**
* Creates a list with all direct child element of the given element.
*
* @param element
* the parent element, cannot be null.
*/
public ElementList(Element element) {
this(element, "*");
}
/**
* Creates a list with all direct child element with a specific local name of the given element.
*
* @param element
* the parent element, cannot be null.
* @param childName
* the local name of the direct child elements that should be added to the list, cannot be null.
*/
public ElementList(Element element, String childName) {
parentName = element.getTagName();
this.childName = childName;
Node child = element.getFirstChild();
while (child != null) {
String newChildName = child.getLocalName();
if (newChildName == null) {
newChildName = child.getNodeName();
}
if (child.getNodeType() == Node.ELEMENT_NODE &&
(childName.endsWith("*") || childName.equals(newChildName))) {
add((Element) child);
}
child = child.getNextSibling();
}
}
/**
* Gets the unique child of this list.
*
* @return
* the sub-element of this element list, never null.
*
* @throws ParseException
* if no child with the specified name was found,
* or if more than one child with the specified name was found.
*/
public Element getUniqueChildElement() throws ParseException {
if (isEmpty()) {
throw new ParseException("No \"" + childName + "\" child found in the \"" + parentName + "\" element.");
} else if (size() > 1) {
throw new ParseException("More than one \"" + childName + "\" children found in the \"" + parentName + "\" element.");
}
return get(0);
}
/**
* Gets the first child of this element.
*
* @return
* the sub-element of this element, or null if no element is found.
*/
public Element getFirstChildElement() {
if (isEmpty()) {
return null;
}
return get(0);
}
}
Author by
YankeeWhiskey
Updated on June 06, 2022Comments
-
YankeeWhiskey about 2 years
I'm trying to read in an XML using DOM in Java
<?xml version="1.0"?> <record> <user> <name>Leo</name> <email>****@****.com</email> <food-list> <food>Hamburgers</food> <food>Fish</food> </food-list> </user> </record>
My current solution is
for (int userNumber = 0; userNumber < masterList.getLength(); userNumber++) { Node singleUserEntry = masterList.item(userNumber); if (singleUserEntry.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element userEntryElement = (org.w3c.dom.Element) singleUserEntry; System.out.println("name : " + getTagValue("name", userEntryElement)); System.out.println("email : " +getTagValue("email", userEntryElement)); NodeList foodList = userEntryElement.getElementsByTagName("food-list").item(0).getChildNodes(); for(int i = 0; i < foodList.getLength(); i++){ Node foodNode = foodList.item(i); System.out.println("food : " + foodNode.getNodeValue()); } private static String getTagValue(String sTag, org.w3c.dom.Element eElement) { NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes(); Node nValue = (Node) nlList.item(0); return nValue.getNodeValue();
And the output now is
name : Leo email : ******@*****.com food : food : null food : food : null food :
Which quite confuses me. Could you tell me where I'm wrong? The number of food tags is not pre-defined.