Issue
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!
Solution
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);
Answered By - VGR
Answer Checked By - Candace Johnson (JavaFixing Volunteer)