I am trying to find the node value by evaluating the xpath expression.
String resp="<response><result><phone>1234</phone><sys_id>dfcgf34dfg56</sys_id></result></response>";
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
org.w3c.dom.Document dDoc = builder.parse(new InputSource(new ByteArrayInputStream(resp.getBytes("utf-8"))));
XPath xPath = XPathFactory.newInstance().newXPath();
Node node = (Node) xPath.evaluate("//response/result/sys_id", dDoc, XPathConstants.NODE);
System.out.println(node.getNodeName()+" , "+node.getNodeValue());
This gives the output : sys_id , null when the sys_id is clearly not null.
The xpath evaluator returns correct value.
Can anybody point out any error?
Thank you!
I am not an expert in XPath, but based on this Stack Overflow article I was able to produce the following code which does work correctly:
String resp = "<response><result><phone>1234</phone><sys_id>dfcgf34dfg56</sys_id></result></response>";
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
org.w3c.dom.Document dDoc = builder.parse(new InputSource(new ByteArrayInputStream(resp.getBytes("utf-8"))));
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile("//response/result/sys_id"); // these 2 lines
String str = (String) expr.evaluate(dDoc, XPathConstants.STRING); // are different
System.out.println(str);
Output:
dfcgf34dfg56
There is a typo in your code: When parsing the input you use a variable called "resp" but you defined a vaiable called "resp1".
Dispite the typo: In order to catch the TextContent use node.getTextContent()
System.out.println(node +": " + node.getNodeName() + ", " + node.getTextContent());
The reason why your code returned null is: You are extracting an ELEMENT node and the result of getNodeValue() depends on the node type (see table in API) and will always return null for ELEMENT nodes.
Related
The XML file is as :
Xml File
Code I have written:
List queryXmlUsingXpathAndReturnList(String xml, String xpathExpression) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance()
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder()
Document doc = dBuilder.parse(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)))
doc.getDocumentElement().normalize()
XPath xPath = XPathFactory.newInstance().newXPath()
NodeList nodeList = (NodeList) xPath.compile(xpathExpression).evaluate(doc, XPathConstants.NODESET)
List returnElements = new ArrayList<>()
nodeList.each { n ->
returnElements.add(n.getTextContent())
}
When I am passing the xpath as:
/Envelope/Body/CommandResponseData/OperationResult/Operation/ParameterList/ListParameter/StringElement
It returns all the values.
But I want to return only the ListParameter values whose name="PackageTypeList".
For that I am using the xpath as:
/Envelope/Body/CommandResponseData/OperationResult/Operation/ParameterList/ListParameter[#name='PackageTypeList']/StringElement
But it returns list as null.
I guess you miss "CommandResult" between "CommandResponseData" and "OperationResult" in your XPath-Expression.
This is my xml and i wanted to fetch value of Id tag '4654'
<Entity>
<acc>
<id>4654</id>
<name>abc</name>
</acc>
<acc>
<id>5465</id>
<name>xyz</name>
</acc>
I am using this code to retrieve the Id value
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(xml)));
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList node = (NodeList) xPath.evaluate("/Entity/acc/id/text()", document, XPathConstants.NODE);
System.out.println("node length:"+node.getLength());
System.out.println("node value:"+ node.item(0).getNodeValue());
return node.item(0).getNodeValue();
Output returns null
Any help would be appreciated
You need to use XPathConstants.NODESET instead of XPathConstants.NODE
or you can keep it as XPathConstants.NODE and change the evaluate to return Node
Node node = (Node) xPath.evaluate("/Entity/acc/id/text()", document, XPathConstants.NODE);
I am using w3c dom library to parse XML. Here I need 3rd parent of element .For example in below XML I am using element.getParentNode()
Input XML
<abc cd="1">
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0">
<current_conditions>
<condition data="Clear">
<item abc ="1" />
</condition>
<temp_f data="49"/>
<temp_c data="9"/>
</current_conditions>
</weather>
</abc>
I have Element eleItem= /item and have to get to parent /weather I am doing it as :
(Element) eleItem.getParentNode().getParentNode().getParentNode();
Is there any other method or using xpath as this doesn't seem to be the right way ?
something likegetXPathParent(eleItem, "../../..")
You are almost there. You could use XPathFactory of java like below :
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( new File( "input.xml" ) );
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
XPathExpression expr = xpath.compile ( "//item/../../..");
Object exprValue = expr.evaluate( doc, XPathConstants.NODE );
if ( exprValue != null && exprValue instanceof Node )
{
Node weatherNode = (Node)exprValue;
System.out.println( weatherNode.getNodeName() );
}
How it works?
The xpath //item/../../.. recursively searches for element item and gets its 3rd level parent.
The XPathConstants.NODE in the evaluate tells Java XPath engine to retrieve it as a Node.
Output will be :
weather
EDIT:
- If you have an element as input :
The following code should give the 3rd parent, where element is item.
public Node getParentNodeUsingXPath( Element element )
{
Node parentNode = null;
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
String nodeName = element.getNodeName();
String expression = "//" + nodeName + "/../../..";
Object obj = xpath.evaluate(expression, element, XPathConstants.NODE );
if ( obj != null )
{
parentNode = (Node)obj;
}
return parentNode;
}
I'm trying to use the DOM library to parse a string in xml format. For some reason my document contains nulls and I run into issues trying to parse it. The string variable 'response' is not null and I am able to see the string when in debug mode.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(response));
Document doc = builder.parse(is);
NodeList nodes = doc.getElementsByTagName("BatchFile");;
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList batchItem = element.getChildNodes();
String uri = batchItem.item(0).getNodeValue();
String id = batchItem.item(1).getNodeValue();
String fqName = batchItem.item(2).getNodeValue();
}
Highlighting over the line Document doc = builder.parse(is); after it has run shows the result of [#document: null].
Edit: I've managed to not got an empty doc now but the string values are still null (at end of code). How would I get the value of something like this
<GetBatchFilesResult>
<BatchFile>
<Uri>uri</Uri>
<ID>id</ID>
<FQName>file.zip</FQName>
</BatchFile>
</GetBatchFilesResult>
You can also use getTextContent(). getNodeValue will return null for elements. Besides, you'd better use getElementsByTagName, since white spaces are also treated as one of the child nodes.
Element element = (Element) nodes.item(i);
String uri = element.getElementsByTagName("Uri").item(0).getTextContent();
String id = element.getElementsByTagName("ID").item(0).getTextContent();
String fqName = element.getElementsByTagName("FQName").item(0).getTextContent();
Check Node API document to see what type of nodes will return null for getNodeValue.
I found the solution. Seems stupid that you have to do it this way to get a value from a node.
Element element = (Element) nodes.item(i);
NodeList batchItem = element.getChildNodes();
Element uri = (Element) batchItem.item(0);
Element id = (Element) batchItem.item(1);
Element fqName = (Element) batchItem.item(2);
NodeList test = uri.getChildNodes();
NodeList test1 = id.getChildNodes();
NodeList test2 = fqName.getChildNodes();
String strURI= test.item(0).getNodeValue();
String strID= test1.item(0).getNodeValue();
String strFQName= test2.item(0).getNodeValue();
The usual queries that I'm currently supporting are from the root , meaning :
public Object evaluate(String expression, QName returnType) {...}
Now I want to do the Xpath query starting from some given Node , e.g. :
public Object evaluate(String expression, Node source, QName returnType) { ? }
Then , If my usual queries look like this (here's an exmaple) :
//load the document into a DOM Document
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("books.xml");
//create an XPath factory
XPathFactory factory = XPathFactory.newInstance();
//create an XPath Object
XPath xpath = factory.newXPath();
//make the XPath object compile the XPath expression
XPathExpression expr = xpath.compile("/inventory/book[3]/preceding-sibling::book[1]");
//evaluate the XPath expression
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
//print the output
System.out.println("1st option:");
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println("i: " + i);
System.out.println("*******");
System.out.println(nodeToString(nodes.item(i)));
System.out.println("*******");
What kind of changes would I need for making this happen for the above method (public Object evaluate(String expression, Node source, QName returnType);)
Thanks!