Java: XML dom parsing retrieves just 1 element of the array - java

I have the following XML (provided by a web service)
<?xml version="1.0" encoding="UTF-8"?>
<itam>
<status>OK</status>
<data>
<item0>
<id>246</id>
<prefisso_quadrato>1</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item0>
<item1>
<id>247</id>
<prefisso_quadrato>2</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item1>
<item2>
<id>248</id>
<prefisso_quadrato>3</prefisso_quadrato>
<id_incontro_corrente />
<id_giornata>65</id_giornata>
<round>R1</round>
<tempo>120</tempo>
<punti_chong>0</punti_chong>
<punti_hong>0</punti_hong>
<amm_chong>0</amm_chong>
<amm_hong>0</amm_hong>
</item2>
</data>
</itam>
I am trying to parse it in JAVA. I can access to the <status> and also to the <data> element. But when I try to iterate over <data> items, I can read just 1 element. This is the code:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
System.out.println(doc.getDocumentElement().getElementsByTagName("data").getLength());
OUTPUT: 1
My idea was something like the code below, but it runs just over the first element (I can read the rest element attributes and then it ends). How can I fix it? Thank you very much
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
NodeList nodelist = doc.getDocumentElement().getElementsByTagName("data");
if(nodelist!=null){
for(int i=0; i<nodelist.getLength(); i++){
Element el = (Element) nodelist.item(i);
//use el to get data from it
}
}

The error is that you are looking for a list of <data> element and you have just one. A solution can be:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document doc = builder.parse(is);
doc.getDocumentElement().normalize();
NodeList items = doc.getDocumentElement().getElementsByTagName("data").item(0).getChildNodes();
for(int i=0; i<items.getLength(); i++){
System.out.println(items.item(i).getNodeName());
}
Good luck!

You will have to recurively iterate over the xml file to get all the elements..
something like this
private Document getDocument(String xsdUrl)
throws ParserConfigurationException, SAXException, IOException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
final DocumentBuilder db = dbf.newDocumentBuilder();
final Document doc = db.parse(xsdUrl);
return doc;
}
private void processElementRecurse(final Element node) throws IOException,
ParserConfigurationException, SAXException, TransformerException {
final NodeList nl = node.getChildNodes();
for (int i = 0, n = nl.getLength(); i < n; i++) {
final Node childNode = nl.item(i);
if (childNode instanceof Element) {
}
else {
processElementRecurse(childElement);
}
}
}

Related

Xml parser with child elements

I have the following xml format and wanted to read the elements in java . 'm very new to xml parsing.
<string xmlns="http://tempuri.org/">
<IDV><exshowroomPrice>48800</exshowroomPrice><idv_amount>46360</idv_amount><idv_amount_min>39406</idv_amount_min><idv_amount_max>53314</idv_amount_max><exshowroomPrice_min>41480</exshowroomPrice_min><exshowroomPrice_max>56120</exshowroomPrice_max><outputmessage></outputmessage></IDV>
<string>
I have added this and after that unable to extract the elements.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(responsebuffer.toString()));
Document doc = db.parse(is);
doc.getDocumentElement().normalize();
System.out.println(doc.getDocumentElement().getTextContent());
NodeList nodes = doc.getChildNodes();
Node no1 = (Node) nodes.item(0);
if (doc.getDocumentElement().getChildNodes().getLength() > 0) {
if (nodes.item(0).getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) nodes.item(0);
NodeList nl =element.getElementsByTagName("exshowroomPrice");
System.out.println(((Node)nl).getNodeValue());
}
}
o/p:<IDV><exshowroomPrice>48800</exshowroomPrice><idv_amount>46360</idv_amount><idv_amount_min>39406</idv_amount_min><idv_amount_max>53314</idv_amount_max><exshowroomPrice_min>41480</exshowroomPrice_min><exshowroomPrice_max>56120</exshowroomPrice_max><outputmessage></outputmessage></IDV>
Kindly help,
Thanks in advance.
I'm not sure I understand your question, but your XML is malformed (it should end with ).
That said, the code to parse your document is correct, now I think the simplest way to extract individual elements would be to use class XPathAPI.
For instance:
Node node = XPathAPI.selectSingleNode(doc, "//string/IDV/exshowroomPrice");
System.out.println(node.getTextContent());
UPDATE:
Actually, XPathAPI is not a standard, but you can use XPath:
XPath xpath = XPathFactory.newInstance().newXPath();
String val = (String) xpath.evaluate("//string/IDV/exshowroomPrice/text()", doc, XPathConstants.STRING);
System.out.println(val);
Finally got the answer.
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(responsebuffer.toString()));
Document document = db.parse(is);
document.getDocumentElement().normalize();
//System.out.println(document.getDocumentElement().getTextContent());
StringBuilder xmlStringBuilder = new StringBuilder();
xmlStringBuilder.append("<?xml version=\"1.0\"?>");
xmlStringBuilder.append(document.getDocumentElement().getTextContent());
ByteArrayInputStream input = new ByteArrayInputStream(xmlStringBuilder.toString().getBytes("UTF-8"));
Document doc = db.parse(input);
NodeList nList = doc.getElementsByTagName("IDV");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println(eElement.getElementsByTagName("exshowroomPrice").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount_min").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("idv_amount_max").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("exshowroomPrice_min").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("exshowroomPrice_max").item(0).getTextContent());
System.out.println(eElement.getElementsByTagName("outputmessage").item(0).getTextContent());
}
}
//getElementsByTagName("exshowroomPrice")
} catch (Exception e) {
e.printStackTrace();
}

getNodeValue() returns some random string

I have an android project with file res/raw/lvl.xml
<?xml version="1.0" encoding="utf-8"?>
<Level>
<dimensions>
<a>5</a>
<b>5</b>
</dimensions>
.
.
.
</Level>
My java code is following
InputStream input = this.getResources().openRawResource(R.raw.lvl);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = buider.parse(input);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
int a = Integer.parseInt(node.getFirstChild().getNodeValue().trim());
The last line throws parsing exception, node.getNodeValue().trim() is "\t\t\n\t".
You're looking at the <dimensions> tag, not at a and b. Look:
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
int a = Integer.parseInt(node.getNodeValue().trim());
You're getting the first (index 0) element of name dimensions. Not its children.
The value you see (\t\t\n\t) is what's left of dimensions' contents after children nodes are removed.
Could not understand what exactly you are trying to do ...but .. you can refer below if that helps
public class Parsing {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
Parsing parse = new Parsing();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("x.xml"));
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("dimensions");
Node node = nList.item(0);
for (Node childNode = node.getFirstChild();
childNode != null;) {
//do something
System.out.println(childNode.getNodeName());
System.out.println(childNode.getTextContent());
Node nextChild = childNode.getNextSibling();
childNode = nextChild;
}
}
}

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);
}
}

Getting value of child node from XML in java

My xml file looks like this
<InNetworkCostSharing>
<FamilyAnnualDeductibleAmount>
<Amount>6000</Amount>
</FamilyAnnualDeductibleAmount>
<IndividualAnnualDeductibleAmount>
<NotApplicable>Not Applicable</NotApplicable>
</IndividualAnnualDeductibleAmount>
<PCPCopayAmount>
<CoveredAmount>0</CoveredAmount>
</PCPCopayAmount>
<CoinsuranceRate>
<CoveredPercent>0</CoveredPercent>
</CoinsuranceRate>
<FamilyAnnualOOPLimitAmount>
<Amount>6000</Amount>
</FamilyAnnualOOPLimitAmount>
<IndividualAnnualOOPLimitAmount>
<NotApplicable>Not Applicable</NotApplicable>
</IndividualAnnualOOPLimitAmount>
</InNetworkCostSharing>
I am trying to get Amount value from <FamilyAnnualDeductibleAmount> and also from <FamilyAnnualOOPLimitAmount>. How do i get those values in java?
You may use two XPath queries /InNetworkCostSharing/FamilyAnnualDeductibleAmount and InNetworkCostSharing/FamilyAnnualOOPLimitAmount or just get the node InNetworkCostSharing and retrieve the values of its two direct children.
Solution using XPath:
// load the XML as String into a DOM Document object
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream("YOUR XML".getBytes());
Document doc = docBuilder.parse(bis);
// XPath to retrieve the content of the <FamilyAnnualDeductibleAmount> tag
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/InNetworkCostSharing/FamilyAnnualDeductibleAmount/text()");
String familyAnnualDeductibleAmount = (String)expr.evaluate(doc, XPathConstants.STRING);
StAX based solution:
XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader rdr = f.createXMLStreamReader(new FileReader("test.xml"));
while (rdr.hasNext()) {
if (rdr.next() == XMLStreamConstants.START_ELEMENT) {
if (rdr.getLocalName().equals("FamilyAnnualDeductibleAmount")) {
rdr.nextTag();
int familyAnnualDeductibleAmount = Integer.parseInt(rdr.getElementText());
System.out.println("familyAnnualDeductibleAmount = " + familyAnnualDeductibleAmount);
} else if (rdr.getLocalName().equals("FamilyAnnualOOPLimitAmount")) {
rdr.nextTag();
int familyAnnualOOPLimitAmount = Integer.parseInt(rdr.getElementText());
System.out.println("FamilyAnnualOOPLimitAmount = " + familyAnnualOOPLimitAmount);
}
}
}
rdr.close();
Note that StAX is especially good for cases like yours, it skips all unnecessary elements reading only the ones you need
Try something like this(use getElementsByTagName to get the parent nodes and then get the value be reaching out to child node):
File xmlFile = new File("NetworkCost.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile );
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("FamilyAnnualDeductibleAmount");
String familyDedAmount = nList.item(0).getChildNodes().item(0).getTextContent();
nList = doc.getElementsByTagName("FamilyAnnualOOPLimitAmount");
String familyAnnualAmount =
nList.item(0).getChildNodes().item(0).getTextContent();
I think I found the solution with this question from stackoverflow
Getting XML Node text value with Java DOM

Get full xml text from Node instance

I have read XML file in Java with such code:
File file = new File("file.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
NodeList nodeLst = doc.getElementsByTagName("record");
for (int i = 0; i < nodeLst.getLength(); i++) {
Node node = nodeLst.item(i);
...
}
So, how I can get full xml content from node instance? (including all tags, attributes etc.)
Thanks.
Check out this other answer from stackoverflow.
You would use a DOMSource (instead of the StreamSource), and pass your node in the constructor.
Then you can transform the node into a String.
Quick sample:
public class NodeToString {
public static void main(String[] args) throws TransformerException, ParserConfigurationException, SAXException, IOException {
// just to get access to a Node
String fakeXml = "<!-- Document comment -->\n <aaa>\n\n<bbb/> \n<ccc/></aaa>";
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(fakeXml)));
Node node = doc.getDocumentElement();
// test the method
System.out.println(node2String(node));
}
static String node2String(Node node) throws TransformerFactoryConfigurationError, TransformerException {
// you may prefer to use single instances of Transformer, and
// StringWriter rather than create each time. That would be up to your
// judgement and whether your app is single threaded etc
StreamResult xmlOutput = new StreamResult(new StringWriter());
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), xmlOutput);
return xmlOutput.getWriter().toString();
}
}

Categories

Resources