Java XML Parse issue [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am facing difficulty in accessing XML value, Can any one let me know what i am missing.
String xml = "<Standard p1:oid=\"00000000-0000-0000-0000-000000f674c1\"\n" +
" xmlns:p1=\"com.iMelt.metaCore.DataObjects.Core\" xmlns=\"com.iMelt.Car.Model.Core\"\n" +
" reasonCode=\"0\">\n" +
" <p1:__info p1:eid=\"00000000-0000-0000-0000-000000000000\">\n" +
" <p1:creationDate>2016-05-28T20:33:45.337+00:00</p1:creationDate>\n" +
" <p1:lastEditorRef>Administrator</p1:lastEditorRef>\n" +
" <p1:version>5</p1:version>\n" +
" </p1:__info>\n" +
" <ChangeState>Approved</ChangeState></Standard>";
byte[] byteArray = xml.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputStream);
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
XPathExpression expr = xpath.compile("/Standard/ChangeState");
Object result = expr.evaluate(doc, XPathConstants.NODESET);

The problem is, is that you don't have nodes called "Standard" and "ChangeState", you have nodes that have namespaced version of Standard and ChangeState.
So you need to use the XPath.setNamespace() method to associate a prefix with a namespace, and then use that prefix in your xpath expressions. Note since you only using the default namespace in your queries, that's all you have to specify, something like
String xml = "<Standard p1:oid=\"00000000-0000-0000-0000-000000f674c1\"\n"
+ " xmlns:p1=\"com.iMelt.metaCore.DataObjects.Core\" xmlns=\"com.iMelt.Car.Model.Core\"\n"
+ " reasonCode=\"0\">\n" + " <p1:__info p1:eid=\"00000000-0000-0000-0000-000000000000\">\n"
+ " <p1:creationDate>2016-05-28T20:33:45.337+00:00</p1:creationDate>\n" + " <p1:lastEditorRef>Administrator</p1:lastEditorRef>\n"
+ " <p1:version>5</p1:version>\n" + " </p1:__info>\n" + " <ChangeState>Approved</ChangeState></Standard>";
byte[] byteArray = xml.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputStream);
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
#Override
public String getNamespaceURI(String prefix) {
return "com.iMelt.Car.Model.Core";
}
#Override
public String getPrefix(String namespaceURI) {
return "x";
}
#Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
});
XPathExpression expr = xpath.compile("/x:Standard/x:ChangeState");
NodeList result = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
The other, less valid option is to remove the statement
factory.setNamespaceAware(true);

The following code outputs "Approved". I have removed factory.setNamespaceAware(true);so that you don't need to specify the default namespace and added code at the end to output the text value.
import java.util.*;
import java.lang.*;
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import javax.xml.xpath.*;
// ...
String xml = "<Standard p1:oid=\"00000000-0000-0000-0000-000000f674c1\"\n" +
" xmlns:p1=\"com.iMelt.metaCore.DataObjects.Core\" xmlns=\"com.iMelt.Car.Model.Core\"\n" +
" reasonCode=\"0\">\n" +
" <p1:__info p1:eid=\"00000000-0000-0000-0000-000000000000\">\n" +
" <p1:creationDate>2016-05-28T20:33:45.337+00:00</p1:creationDate>\n" +
" <p1:lastEditorRef>Administrator</p1:lastEditorRef>\n" +
" <p1:version>5</p1:version>\n" +
" </p1:__info>\n" +
" <ChangeState>Approved</ChangeState></Standard>";
byte[] byteArray = xml.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(byteArray);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(inputStream);
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
XPathExpression expr = xpath.compile("/Standard/ChangeState");
NodeList result = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);
Node node = result.item(0);
System.out.println(node.getTextContent());

Related

Unable to parse XML using java

I have an XML string got as a response. But I am unable to reach at Response Code and remarks. Can anybody help me to get the response code.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetIMEIInfoResponse xmlns="http://tempuri.org/">
<GetIMEIInfoResult>
<![CDATA[
<SerialsDetail>
<Item>
<ResponseCode>2</ResponseCode>
<Remark>Invalid Input</Remark>
</Item>
</SerialsDetail>
]]>
</GetIMEIInfoResult>
</GetIMEIInfoResponse>
</s:Body>
</s:Envelope>
Thats how I am trying to do
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(response)));
NodeList list = doc.getElementsByTagName("Remark");
System.out.println(list.getLength());
Node n = list.item(0);
System.out.println(n.getTextContent());
} catch (Exception e) {
e.printStackTrace();
}
You are asking for an element with name "Remark", but you document does not contain such an element. Instead, it contains only an "GetIMEIInfoResult" element with a bunch of text in it. This text happens to be xml. But in order to access the contents of the inner piece of XML, you have to parse the contents of the "GetIMEIInfoResult" in the same way that you've parsed the entire document.
Here is how you can do it:
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
public class NestedCDATA {
private static String response =
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
" <s:Body>" +
" <GetIMEIInfoResponse xmlns=\"http://tempuri.org/\">" +
" <GetIMEIInfoResult>" +
" <![CDATA[" +
" <SerialsDetail>" +
" <Item>" +
" <ResponseCode>2</ResponseCode>" +
" <Remark>Aawwwwwwww yeaaaah!</Remark>" +
" </Item>" +
" </SerialsDetail>" +
" ]]>" +
" </GetIMEIInfoResult>" +
" </GetIMEIInfoResponse>" +
" </s:Body>" +
"</s:Envelope>";
public static String getCdata(Node parent) {
NodeList cs = parent.getChildNodes();
for(int i = 0; i < cs.getLength(); i++){
Node c = cs.item(i);
if(c instanceof CharacterData) {
CharacterData cdata = (CharacterData)c;
String content = cdata.getData().trim();
if (content.length() > 0) {
return content;
}
}
}
return "";
}
public static void main(String[] args) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(response)));
Node cdataParent = doc.getElementsByTagName("GetIMEIInfoResult").item(0);
DocumentBuilder cdataBuilder = factory.newDocumentBuilder();
Document cdataDoc = cdataBuilder.parse(new InputSource(new StringReader(
getCdata(cdataParent)
)));
Node remark = cdataDoc.getElementsByTagName("Remark").item(0);
System.out.println("Content of Remark in CDATA: " + getCdata(remark));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Result: "Content of Remark in CDATA: Aawwwwwwww yeaaaah!".
Here is another interesting question for you: why does your service output XML with XML in it? XML all by itself is already nested enough. Is it really necessary to wrap parts of it in CDATA?
The problem of the XML is that the data in the tag GetIMEIInfoResult is CDATA. This causes the builder not to recognize it as XML. To access the data in the tag GetIMEIInfoResult you can use the following:
Element infoResult = (Element) list.item(0);
String elementData = getCharacterDataOfNode(infoResult.getFirstChild());
public static String getCharacterDataOfNode(Node node) {
String data = "";
if (node instanceof CharacterData) {
data = ((CharacterData) node).getData();
}
return data;
}
Then you have to parse that data again with a DocumentBuilder where you can access the tag Remark. To get the content you have again work with the getCharacterDataOfNode() method.

SoapFaultException - extract code and text

I want to extract code and text separately from the soap fault listed below. The code that I am using (listed below xml) is printing code and text together.
<env:Fault xmlns:env = "http://schemas.xmlsoap.org/soap/envelope/" xmlns:fault = "http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>fault:Client</faultcode>
<faultstring>An error occurred. Please check the detail section.</faultstring>
<detail>
<e:serviceFault xmlns:e = "http://xml.comcast.com/types">
<e:messages>
<e:message>
<e:code>ERRORCODE-82828</e:code>
<e:text>Error Message.</e:text>
</e:message>
</e:messages>
</e:serviceFault>
</detail>
</env:Fault>
Code
public void printSoapFaultClientException(SoapFaultClientException e) {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = null;
transformer = transformerFactory.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(e.getSoapFault().getSource(), result);
NodeList nl = ((Document)result.getNode()).getElementsByTagName("detail");
System.out.println(" text content " + ((Element)nl.item(0)).getTextContent());
}
Here is an example of doing it , since it is a fault XML , i have just used a parser to parse the XML and extract a field off it. Also SOAPFaultClientException API's can help you extract the fault reason directly if you want it (http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/soap/client/SoapFaultClientException.html)
File fXmlFile = new File("C:\\DevelopmentTools\\3.CODE\\SOAP.txt");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
XPath xpath = XPathFactory.newInstance().newXPath();
String responseStatus = xpath.evaluate("//*[local-name()='code']/text()", doc);
String responseText = xpath.evaluate("//*[local-name()='text']/text()", doc);
System.out.println("---> " + responseStatus);
System.out.println("---> " + responseText);

Document.toString() is "[#document: null]" even though XML was parsed

Consider this example
#Test
public void testXML() {
final String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><results>\n" +
" <status>OK</status>\n" +
" <usage>By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www.alchemyapi.com/company/terms.html</usage>\n" +
" <url/>\n" +
" <language>english</language>\n" +
" <docSentiment>\n" +
" <type>neutral</type>\n" +
" </docSentiment>\n" +
"</results> ";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try
{
builder = factory.newDocumentBuilder();
Document doc = builder.parse( new InputSource( new StringReader( s ) ) );
System.out.println(doc.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
When I run this example
System.out.println(doc.toString()); turns out to be [#document: null].
I also validated this XML online and no errors were found. What am I missing?
What I need?
I need to find out value of <docSentiment> in this XML
Thanks
As per MadProgrammer's advice, I managed to get the value.
Note: Even though [#document: null] was shown, the document was not null, in reality.
#Test
public void testXML() {
final String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><results>\n" +
" <status>OK</status>\n" +
" <usage>By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www.alchemyapi.com/company/terms.html</usage>\n" +
" <url/>\n" +
" <language>english</language>\n" +
" <docSentiment>\n" +
" <type>neutral</type>\n" +
" </docSentiment>\n" +
"</results>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try
{
builder = factory.newDocumentBuilder();
Document doc = builder.parse( new InputSource( new StringReader( s ) ) );
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//docSentiment/type");
NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
System.out.println("Sentiment:" + ((DTMNodeList) nl).getDTMIterator().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
and I go the output as
Sentiment:neutral

Read inside a Tag using XPath Java

Hye I am new to read XML File using Java my problem is that I have been trying to read an xml and between a specific tag I want to get the required data I am using XPath and my query is:
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#type='STRING']";
It works fine and my specific Tag to read from is:
<ATTRIBUTE name="Description" type="STRING"> SOME TEXT </ATTRIBUTE>
But I want to read the data inside only these types of Tags so that my output should be:
SOME TEXT
inside the tag!
can somebody help me how can I do this Please I am new to xml reading! Trying my best as:
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description' and ./type/text()='STRING']";
But it wont give me any output!
thanks in advance
My Code:
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(
new FileInputStream("c:\\y.xml"));
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'and #type='STRING']";
System.out.println(expression);
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
} catch (ParserConfigurationException | SAXException | IOException e) {
System.out.print(e);
}
There is a problem with my code cant figure out what!
This code works fine for me with the changed XPath to:
"/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'][#type='STRING']":
private static final String EXAMPLE_XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<ADOXML adoversion=\"Version 5.1\" username=\"kvarga\" database=\"adonisdb\" time=\"08:55\" date=\"30.11.2013\" version=\"3.1\">" +
"<MODELS>" +
"<MODEL version=\"\" applib=\"ADONIS BPMS BP Library 5.1\" libtype=\"bp\" modeltype=\"Business process model\" name=\"Product development\" id=\"mod.25602\">" +
"<MODELATTRIBUTES>" +
"<ATTRIBUTE name=\"Version number\" type=\"STRING\"> </ATTRIBUTE>" +
"<ATTRIBUTE name=\"Author\" type=\"STRING\">kvarga</ATTRIBUTE>" +
"<ATTRIBUTE name=\"Description\" type=\"STRING\">I WANT THIS PARA 2</ATTRIBUTE>" +
"</MODELATTRIBUTES>" +
"</MODEL>" +
"</MODELS>" +
"</ADOXML>";
public static void main(String[] args) {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(EXAMPLE_XML.getBytes()));
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE[#name='Description'][#type='STRING']";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println("###" + nodeList.item(i).getFirstChild().getNodeValue() + "###");
}
} catch (Exception e) {
System.out.print(e);
}
}
OUTPUT:
###I WANT THIS PARA 2###
The mentioned code works fine.
You can try other way also to get the text node -
String expression = "/ADOXML/MODELS/MODEL/MODELATTRIBUTES/ATTRIBUTE/text()";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
System.out.println(nodeList.item(0).getNodeValue());

How to retrieve/extract XML element attribute value

I have an XML like the following,
<?xml version="1.0" encoding="utf-8"?>
<PaymentElement>
<Payment seqID="3">
<TPayment>
<Status>status</Status>
</TPayment>
</Payment>
</PaymentElement>
The question is how do I retrieve/extract seqID value which is 3 out of this via java.
I have tried the following way, but it doesn't work.
InputStream xml = conn.getInputStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(xml);
NodeList list = doc.getElementsByTagName("PaymentElement");
for(int i=0; i<=list.getLength();i++){
NodeList paySeq=doc.getElementsByTagName("Payment seqID");
System.out.println("Payment seqID"+paySeq);
}
try
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File("1.xml"));
Element e = (Element)doc.getDocumentElement().getElementsByTagName("Payment").item(0);
String id = e.getAttribute("seqID");
System.out.println("Payment seqID = " + id);
output
Payment seqID = 3
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/PaymentElement/Payment/#seqID");
Object result = expr.evaluate(doc, XPathConstants.STRING);
result should be having 3 now.
Full Example
import java.io.*;
import javax.xml.xpath.*;
import org.xml.sax.InputSource;
public class Demo {
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream("sample.xml");
InputSource inputSource = new InputSource(inputStream);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/PaymentElement/Payment/#seqID");
Object result = expr.evaluate(inputSource, XPathConstants.STRING);
System.out.println(result);
}
}

Categories

Resources