Parsing xml name-value fields - java

In my xml, I am seraching for speciffic names and want to retrieve their value.
for example i have this field:
<n0:field>
<n0:name n4:type="n3:string" xmlns:n3="http://www.w3.org/2001/XMLSchema" xmlns:n4="http://www.w3.org/2001/XMLSchema-instance">LifePolicyID</n0:name>
<n0:value n6:type="n5:string" xmlns:n5="http://www.w3.org/2001/XMLSchema" xmlns:n6="http://www.w3.org/2001/XMLSchema-instance">1</n0:value>
</n0:field>
I try to get the value of the LifePolicyID name.
Is there a way to do it programatticly?
Right now i am usin Xpath like this:
XPathExpression xpe = xpath.compile("//*[name/text()='" + name +"']/value");
Where name is in this case is LifePolicyID. But it dont work.
Any ideas?

Your code seems to work for me
String xml =
"<n0:field xmlns:n0='http://test/uri'>" +
" <n0:name n4:type='n3:string' xmlns:n3='http://www.w3.org/2001/XMLSchema' xmlns:n4='http://www.w3.org/2001/XMLSchema-instance'>LifePolicyID</n0:name>" +
" <n0:value n6:type='n5:string' xmlns:n5='http://www.w3.org/2001/XMLSchema' xmlns:n6='http://www.w3.org/2001/XMLSchema-instance'>1</n0:value>" +
"</n0:field>";
String name = "LifePolicyID";
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression xpe = xpath.compile("//*[name/text()='" + name +"']/value");
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
System.out.println(xpe.evaluate(doc));

Related

XPath compiling behaviour

I am testing my application and realised that behaviour is different when compiling.
For example, if my expression to compile is :
XPathExpression expr = xPath.compile("/DocDetails/TransactionSignature");
And :
XPathExpression expr2 = xPath.compile("/DocDetails/" + x);
x is declared as a String datatype.
Lets say that x in expr2 is "abc", XPathExpression is compiled with no issues.
But if x in expr2 is "123abc" OR "123", XPathExpression throws a :
javax.xml.transform.TransformerException: A location step was expected
following the '/' or '//' token.
Just curious regarding this behaviour..
Here is the full code for reference:
String document = "C:/Users/Eunice/Documents/MITS/doc.xml";
String document2 = "C:/Users/Eunice/Documents/MITS/doc2.xml";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(document);
Document doc2 = builder.parse(document2);
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
XPathExpression expr = xPath.compile("/DocDetails/TransactionSignature");
Node node = (Node)expr.evaluate(doc, XPathConstants.NODE);
String x = node.getTextContent();
System.out.println(x);
XPathExpression expr2 = xPath.compile("/DocDetails/" + x);
Node node2 = (Node)expr2.evaluate(doc2, XPathConstants.NODE);
if (node2 == null)
System.out.println("null");
else
System.out.println("not null " + node2.getTextContent());
And this is the XML file:
<DocDetails>
<TransactionSignature>abc123</TransactionSignature>
</DocDetails>
But if x in expr2 is "123abc" OR "123", XPathExpression throws a
XML element name cannot start with number. Hence your example is equivalent to
XPathExpression expr2 = xPath.compile("/DocDetails/123abc");
I guess XPath parser does not expect it.
You should also provide full XML. I believe it certainly does not contain anything like <DocDetails><TransactionSignature>abc123</TransactionSignature><123abc>something</123abc></DocDetails>. This is simply invalid XML.
I finally found the answer after much searching!
It is actually illegal to start an element tag with numbers.
As can be seen in this stackoverflow answer
Originally, this line was throwing an transformer exception:
XPathExpression expr2 = xPath.compile("/DocDetails/" + x);
Since it is illegal to start with numbers, they are probably reading it as an invalid tag.
Which means this line is actually reading "/DocDetails/" instead of "/DocDetails/123" OR "/DocDetails/123abc",
causing the extra '/' at the end, hence throwing an transformer exception.

how to parse xml to java in nodelist

that is my xml
<?xml version = "1.0" encoding = "UTF-8"?>
<ns0:GetADSLProfileResponse xmlns:ns0 = "http://">
<ns0:Result>
<ns0:eCode>0</ns0:eCode>
<ns0:eDesc>Success</ns0:eDesc>
</ns0:Result>
</ns0:GetADSLProfileResponse>
that is my code in java I need to know how to start in this
I tried some code online but still did not solve my problem
how to get the values in the result to loop in it and get 0 in ecode and Success in eDesc
CustomerProfileResult pojo = new CustomerProfileResult();
String body = readfile();
System.out.println(body);
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse(new InputSource(new StringReader(body)));
XPath xpath =XPathFactory.newInstance().newXPath();
XPathExpression name = xpath.compile("/xml/GetADSLProfileResponse/Result");
NodeList nodeName = (NodeList) name.evaluate(dom, XPathConstants.NODESET);
if(nodeName!=null){
}
Summary
You can try to following expression which allows you to select nodes without caring the namespace ns0:
/*[local-name()='GetADSLProfileResponse']/*[local-name()='Result']/*
Explanation
In your syntax, several parts were incorrect. Let's take a look together. XPath syntax /xml means that the root node of the document is <xml>, but the root element is <ns0:GetADSLProfileResponse>; GetADSLProfileResponse is incorrect too, because your XML file contains a namespace. Same for Result:
/xml/GetADSLProfileResponse/Result
In my solution, I ignored the namespace, because your namespace provided is incomplet. Here's a full program to get started:
String XML =
"<?xml version = \"1.0\" encoding = \"UTF-8\"?>\n"
+ "<ns0:GetADSLProfileResponse xmlns:ns0 = \"http://\">\n"
+ " <ns0:Result>\n"
+ " <ns0:eCode>0</ns0:eCode>\n"
+ " <ns0:eDesc>Success</ns0:eDesc>\n"
+ " </ns0:Result>\n"
+ "</ns0:GetADSLProfileResponse> ";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document;
try (InputStream in = new ByteArrayInputStream(XML.getBytes(StandardCharsets.UTF_8))) {
document = builder.parse(in);
}
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile("/*[local-name()='GetADSLProfileResponse']/*[local-name()='Result']/*");
NodeList nodeList = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
System.out.println(node.getNodeName() + ": " + node.getTextContent());
}
It prints:
ns0:eCode: 0
ns0:eDesc: Success
See also:
How to query XML using namespaces in Java with XPath?
Node (Java Platform SE 8)

Xpath display correct results in XMLSpy but null in Java

I am trying to display all text within text nodes only, within an XFA XML document while ignoring namespaces.
I came up with an Xpath that returns the desired results within XMLSpy with xpath 1.0 but the same Xpath in Java returns null for some reason.
Xpath = //*[local-name()='text'][string-length(normalize-space(.))>0]
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
ArrayList<String> list = new ArrayList<>();
XPathExpression expr = xpath.compile("//*[local-name()='text'][string-length(normalize-space(.))>0]");
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println("This prints null = " + nodes.item(i).getNodeValue());
}
XML file wouldn't post here so it can be viewed at the link below:
https://drive.google.com/file/d/1n-v3gzT-3GgxNnYKFUvMPjRQmtnkqcpY/view?usp=sharing
The problem is that it's not the <text> elements that contain the values, but their child text nodes.
Replace the line
System.out.println("This prints null = " + nodes.item(i).getNodeValue());
with
System.out.println("This does not print null = " + nodes.item(i).getFirstChild().getNodeValue());

How to get xml attribute values using Document builder factory

How to get attribute values by using the following code i am getting ; as output for msg . I want to print MSID,type,CHID,SPOS,type,PPOS values can any one solve this issue .
String xml1="<message MSID='20' type='2635'>"
+"<che CHID='501' SPOS='2'>"
+"<pds type='S'>"
+"<position PPOS='S01'/>"
+"</pds>"
+"</che>"
+"</message>";
InputSource source = new InputSource(new StringReader(xml1));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(source);
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
String msg = xpath.evaluate("/message/che/CHID", document);
String status = xpath.evaluate("/pds/position/PPOS", document);
System.out.println("msg=" + msg + ";" + "status=" + status);
You need to use # in your XPath for an attribute, and also your path specifier for the second element is wrong:
String msg = xpath.evaluate("/message/che/#CHID", document);
String status = xpath.evaluate("/message/che/pds/position/#PPOS", document);
With those changes, I get an output of:
msg=501;status=S01
You can use Document.getDocumentElement() to get the root element and Element.getElementsByTagName() to get child elements:
Document document = db.parse(source);
Element docEl = document.getDocumentElement(); // This is <message>
String msid = docEl.getAttribute("MSID");
String type = docEl.getAttribute("type");
Element position = (Element) docEl.getElementsByTagName("position").item(0);
String ppos = position.getAttribute("PPOS");
System.out.println(msid); // Prints "20"
System.out.println(type); // Prints "2635"
System.out.println(ppos); // Prints "S01"

Parse XML with XPath & namespaces in Java

Can you help me adjust this code so it manages to parse the XML? If I drop the XML namespace it works:
String webXmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<foo xmlns=\"http://foo.bar/boo\"><bar>baz</bar></foo>";
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse(new StringInputStream(webXmlContent));
NamespaceContextImpl namespaceContext = new NamespaceContextImpl();
namespaceContext.startPrefixMapping("foo", "http://www.w3.org/2001/XMLSchema-instance");
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(namespaceContext);
XPathExpression expr = xpath.compile("/foo/bar");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
System.out.println("Got " + nodes.getLength() + " nodes");
You must use a prefix in your XPath, e. g.: "/my:foo/my:bar" You can choose any prefix you like - it doesn't have anything to do with the prefixes you use or don't use in the XML file - but you must choose one. This is a limitation of XPath 1.0.
You must perform prefix mapping from "my" to "http://foo.bar/boo" (not to "http://www.w3.org/2001/XMLSchema-instance")

Categories