Find a Element by attribute in a XML Document in Java and get value of another attribute in the same element
Question:
I was tasked to convert some of my Python code to Java.
In the original there is a lot of operations like this:
name = element.find('*/DIAttribute[@name="ui_display_name"]').attrib['value']
Where element is a lxml.etree.Element
object.
In Java I’m doing this to get the same value:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodesName = (NodeList) xPath.evalute("DIAttribute[@name='ui_display_name']", element, XPathConstants.NODE);
if nodesName.getLength() > 0 {
Node node = nodesName.item(0);
name = node.getAttributes().getNamedItem("value");
}
I’m doing it right? There is a better way of doing this? I’m using the org.w3c.dom
objects, and the powers that be forbid me of using other XML libraries.
Thanks!
Answers:
Passing XPathConstants.NODE does not cause evaluate
to return a NodeList, it causes the method to return a single Node. The class documentation describes exactly what type of object will be returned for each XPathConstant field.
Node node = (Node) xPath.evaluate("DIAttribute[@name='ui_display_name']", element, XPathConstants.NODE);
Attributes are document nodes too, so you can simplify the code into a single XPath expression:
Node node = (Node) xPath.evaluate("DIAttribute[@name='ui_display_name']/@value", element, XPathConstants.NODE);
String name = node.getNodeValue();
Since you just want the string value of the node, you can use the two-argument evaluate method instead, omitting the XPathConstants value:
String name = xPath.evaluate("DIAttribute[@name='ui_display_name']/@value", element);
That will only find DIAttribute elements which are direct children of element
. If you want to search all DIAttribute descendants at all levels below element
, use .//
in your XPath expression:
String name = xPath.evaluate(".//DIAttribute[@name='ui_display_name']/@value", element);
I was tasked to convert some of my Python code to Java.
In the original there is a lot of operations like this:
name = element.find('*/DIAttribute[@name="ui_display_name"]').attrib['value']
Where element is a lxml.etree.Element
object.
In Java I’m doing this to get the same value:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodesName = (NodeList) xPath.evalute("DIAttribute[@name='ui_display_name']", element, XPathConstants.NODE);
if nodesName.getLength() > 0 {
Node node = nodesName.item(0);
name = node.getAttributes().getNamedItem("value");
}
I’m doing it right? There is a better way of doing this? I’m using the org.w3c.dom
objects, and the powers that be forbid me of using other XML libraries.
Thanks!
Passing XPathConstants.NODE does not cause evaluate
to return a NodeList, it causes the method to return a single Node. The class documentation describes exactly what type of object will be returned for each XPathConstant field.
Node node = (Node) xPath.evaluate("DIAttribute[@name='ui_display_name']", element, XPathConstants.NODE);
Attributes are document nodes too, so you can simplify the code into a single XPath expression:
Node node = (Node) xPath.evaluate("DIAttribute[@name='ui_display_name']/@value", element, XPathConstants.NODE);
String name = node.getNodeValue();
Since you just want the string value of the node, you can use the two-argument evaluate method instead, omitting the XPathConstants value:
String name = xPath.evaluate("DIAttribute[@name='ui_display_name']/@value", element);
That will only find DIAttribute elements which are direct children of element
. If you want to search all DIAttribute descendants at all levels below element
, use .//
in your XPath expression:
String name = xPath.evaluate(".//DIAttribute[@name='ui_display_name']/@value", element);