When I am printing my API response, which gives me below xml as Response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BugInfo xmlns="ctessng" xmlns:ns2="http://www.w3.org/1999/xlink">
<Bug id="CSCvz53137">
<Field name="Assigned Date">09/01/2021 21:12:25</Field>
<Field name="Archived">N</Field>
<Field name="Assigner">James Vilson</Field>
<Field name="Status">V</Field>
<Field name="Submitter">Spark Mery</Field>
<Field name="Reason">Technically Inaccurate</Field>
<Field name="Regression">Y</Field>
<Field name="Resolved Date">09/02/2021 02:12:37</Field>
<Field name="Version">001.010</Field>
</Bug>
</BugInfo>
I want to fetch only specific values form this xml, like Assigned Date, Assigner, Submitter & Resolved-on
Assigned Date --> 09/01/2021 21:12:25
Assigner --> James Vilson
Submitter --> Spark Mery
Resolved Date --> 09/02/2021 02:12:37
What is the best/simplest way to read in values from this xml?
Regex
The most versatile would be plain text-filtering (match/find, extract) using a regular expression:
<Field name=\"(Assigned Date|Assigner|Submitter|Resolved Date)\">(.*)<
Iterating with find() then group(1) and group(2) can give you the desired strings.
See this regex demo
XPath
The pure XML-parsing way would be to use any XML parser, like DocumentBuilderFactory and SAXParser which can be used to read the XML into a document, then find the desired XML-nodes (Field elements) via XPath expression:
/BugInfo/Bug/Field[#name="Assigner"]|//Field[#name="Assigned Date"]|//Field[#name="Submitter"]|//Field[#name="Resolved Date"]
Iterating over the found nodes we can extract the child as text value.
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xPath.compile(xPathExpression).evaluate(xmlDocument, XPathConstants.NODESET);
See:
Filtering XML Document using XPATH in java
XPath OR operator for different nodes
XML mapping
The object-oriented way would use an XML mapper like Jackson to deserialize (unmarshall) the XML to an object.
Similar to the OkHTTP Recipe: Parse a JSON Response With Moshi (.kt, .java)
Then you would need a class where you can map the XML nodes to.
class Bug {
String submitter;
String assigner;
Date assignedOn;
Date resolvedOn
}
The mapping can be a bit tricky here, because from XML-model point-of-view a Bug node contains a collection of children Fields. But the target type, is semantically not a field-list, but a Bug-object with different typed properties.
This is probably the cleanest because it will be easy to parse: Bug bug = new XmlMapper().readValue(xmlString, Bug.class).
Related
I am using Java to extract values using XPath. I was able to extract elements under the element fields but the elements under records are not returned.
XML is as follows:
<?xml version="1.0" ?>
<qdbapi>
<action>****</action>
<errcode>0</errcode>
<errtext>No error</errtext>
<qid>****</qid>
<qname>****</qname>
<table>
<fields>
<field id="19" field_type="text" base_type="text">
</field>
</fields>
<records>
<record>
<f id="6">1</f>
</record>
</records>
</table>
</qdbapi>
Code below:
XMLDOMDocObj.selectNodes("//*[local-name()='fields']")//21 fields returned
XMLDOMDocObj.selectNodes("//*[local-name()='records']")//no records are returned
XML must have a single root element; yours has two: fields and records.
Wrap them in a single common root to get the results you expect.
Also, if your XML has no namespaces, there's no reason to defeat them. Instead of
//*[local-name()='records']
use
//records
See also
How does XPath deal with XML namespaces?
Why must XML documents have a single root element?
What is the difference between root node, root element and document element in XML?
I'm unmarshaling a couple of large XML files.
they have the common part and I decided to write the common parts in separate XML file and then include it using xi:include tag.
it looks like this:
<tag1>
<tag2>
</tag2>
<tag3>
</tag3>
<xi:include href = "long/common/part/of/partial/xml/file1"/>
<xi:include href = "long/common/part/of/partial/xml/file2"/>
</tag1>
at this moment I would like to parametrize the long/common/part.
I tried to define a variable using xsl:variable like this
<xsl:variable name="test">
"long/common/part/of/partial/xml/"
</xsl:variable>
but the assigning value to href was a problem, neither the
<xi:include href = "{$test}"/>
or
<xi:include href = <xsl:value-of select="test"/>
wasn't working.
Is there a way to assign value to XML attribute?
You're mixing XInclude, XSLT, and ad-hoc {$var} syntax (not part of XML) here. What you can do to parametrize a href value in XInclude elements is to use an entity reference (XML's and SGML's mechanism for text substitution variables among other things):
<xi:include href="&href-value;"/>
where href-value must be bound to the string long/common/part/of/partial/xml/file1 either programmatically, or (preferably) by declaring it in the prolog eg:
<!DOCTYPE tag1 [
<!ENTITY href-value "long/common/part/of/partial/xml/file1">
]>
<tag1>
<xi:include href = "&href-value;"/>
</tag1>
However, since now you're using entity references anyway, you can achieve just the same with just entities, and without XInclude at all:
<!DOCTYPE tag1 [
<!ENTITY common-part SYSTEM "long/common/part/of/partial/xml/file1">
]>
<tag1>
&common-part;
</tag1>
This pulls the content of long/common/part/of/partial/xml/file1 into the common-part entity, then references that value in content, with the XML parser treating the document as if the replacement value for common-part (eg. whatever is stored in long/common/part/of/partial/xml/file1) had been specified directly in the document.
Hope this isn't too confusing; there's a general explanation how entities in XML and SGML work in this answer
I want to try parse xml with XPath in Android Application.
My XML file looks like this.
<expenses>
<entry type="fixed">
<amount>200</amount>
<recurring>true</recurring>
<category>Home/Rent</category>
<payee>Ahmet Necati</payee>
<account>1</account>
<startDate>2013-01-01</startDate>
<endDate>2013-01-01</endDate>
</entry>
<entry type="variable">
<amount>150</amount>
<category>Departmental</category>
<payee>Ahmet Necati</payee>
<recurring>true</recurring>
<startDate>2013-01-01</startDate>
<endDate>2013-01-01</endDate>
<account>1</account>
</entry>
</expenses>
and I want to try parse xml with xPath like that
String expression = "/expenses/entry[xs:date(endDate) < xs:date('2013-10-10')]";
NodeList widgetNode = (NodeList) xpath.evaluate(expression, document,
XPathConstants.NODESET);
But I couldnt deal with it. It returns 0 node.
Edit: I want to get all nodes "endDate" less than spesific date for example: I want to get nodes which end Date less than "2013-10-10"
The "XML schema constructor functions" are part of XPath 2.0, but Android only supports XPath 1.0: http://developer.android.com/reference/javax/xml/xpath/package-summary.html
One solution is to register your own function to do the conversion (see XPathFunctionResolver). Another is to look into libraries that support XPath 2.0.
i have response structure that i want to parse in Java. Can anyone help me with this?
<message_response xmlns="">
<action name="GETCIL">
<param name="bookingNote" value="" require="" read-only=""><![CDATA[bookingNote]]></param>
<param name="CarrierLinkType" value="" require="" read-only=""><![CDATA[True]]></param>
<param name="Carrier" value="" require="" read-only=""><![CDATA[SK185]]></param>
<param_list name="ViaAddressList" id="GETCIL">
<value>
<param_list name="ViaAddressId" id="ViaAddressList">
<value><![CDATA[877765050_5511]]></value>
</param_list>
<param_list name="AddressDate" id="ViaAddressList">
<value><![CDATA[10/12/2010]]></value>
</param_list>
<param_list name="AddressTime" id="ViaAddressList">
<value><![CDATA[12:12]]></value>
</param_list>
</value>
</param_list>
</action>
</message_response>
The easiest way to extract specific values from an XML document (as opposed to parsing the complete document with SAX) is to use XPath as follows:
//1. load the document into memory.
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//2. Create an XPath.
XPath xpath = XPathFactory.newInstance().newXPath();
//3. Evaluate the xpath expression.
String actionName = xpath.evaluate("/message_response/action/#name", documentBuilder.parse(xmlFile));
There's not much more to it other than the XPath.evaluate method is overloaded in order to allow nodes and node lists to be returned (see javax.xml.xpath.XPathConstants for the types).
Then you just need to read-up on the xpath syntax (http://www.w3schools.com/xpath/xpath_syntax.asp).
Why the CDATA sections around the data?
You can use SAX or DOM to parse XML.
There are also libraries wrapping SAX and DOM parsers that make your life easier for common tasks. Two that come to mind for Java are JDOM and DOM4J. Google for them - there are tutorials and examples available that will show you what you need to know.
I have a xml document like this rootXMLDoc=<root> <param></param></root> . I need to insert paramxmlDoc= <parameter par='1'>abc</parameter>. how to insert paramxmlDoc to rootXMLDoc in java.? and i need output like this
<root>
<parameter par='1'>abc</parameter>
<param></param>
</root>
Like this:
Element e = paramxmlDoc.getRootElement();
paramxmlDoc.setRootElement(null); // break connection between doc and element
rootXMLDoc.getRootElement().addChild(e); // Insert node in other document
Note: This is from memory, so the actual method calls can be slightly different but you get the idea.