java xml dom parsing - java

I have this project I'm working on where I want to parse an xml file that looks like this:
<?xml version='1.0' encoding='UTF-8'?>
<projectlist>
<project>
<name>SuperDuperApp</name>
<type>batch</type>
<prod>
<server>testserver01</server>
</prod>
<qa>
<server>testserver01</server>
</qa>
<dev>
<server>testserver01</server>
</dev>
</project>
<project>
<name>Calculator</name>
<type>deploy</type>
<prod>
<server>testserver02</server>
<server>testserver03</server>
<server>testserver04</server>
</prod>
<qa>
<server>testserver05</server>
<server>testserver06</server>
<server>testserver07</server>
</qa>
<dev>
<server>testserver12</server>
<server>testserver13</server>
<server>testserver14</server>
</dev>
</project>
</projectlist>
With this method parsing the file and trying to print out in the format:
name: SuperDuperApp
type: batch
server: testserver01
name: Calculator
type: deploy
environment: dev
server: testserver12
server: testserver13
server: testserver14
etc.
public void parseXML() {
ArrayList al = new ArrayList();
HashSet hs = new HashSet();
try {
InputStream file = this.getClass().getResourceAsStream(
"/net/swing/sandbox/util/config/projectlist.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("project");
System.out.println("Information of all servers...");
for (int i=0;i<nList.getLength();i++){
Node fstNode = nList.item(i);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElement = (Element) fstNode;
NodeList nameElementList = fstElement.getElementsByTagName("name");
Element nameElement = (Element) nameElementList.item(0);
NodeList name = nameElement.getChildNodes();
System.out.println("project name: " + ((Node) name.item(0)).getNodeValue());
hs.add(((Node) name.item(0)).getNodeValue());
NodeList typeElementList = fstElement.getElementsByTagName("type");
Element typeElement = (Element) typeElementList.item(0);
NodeList type = typeElement.getChildNodes();
System.out.println("Deploy type: " + ((Node) type.item(0)).getNodeValue());
//print out server list can't do it for some reason
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
al.clear();
al.addAll(hs);
Collections.sort(al);
for (int z = 0; z < al.size(); z++) {
listModel.addElement(al.get(z));
}
} catch (Exception e) {
e.printStackTrace();
}
lstProject.validate();
}
So I rewrote my method and now I'm just stuck <---newb

Check the documentation for Node. Each node has a method getChildNodes. Check that for the existence of children nodes and than iterate over them like you are doing.

If your xml was created using an xsd schema, you could instead use JAXB to create classes for it, using the xjc tool. That should make your life a bit easier.

I think it's appropriate to use XSLT transform in your case (much less boilerplate code) Look at TransformerFactory and java api for xml processing.

As a q&d solution you could apply the same strategy as for getting "project" node:
...
System.out.println("servers:");
NodeList sList = eElement.getElementsByTagName("server");
for (int i = 0; i < sList.getLength(); i++) {
String stuff = sList.item(i).getFirstChild().getNodeValue();
System.out.println(stuff);
}

Related

Need to iterate an xml with child nodes with same name

I have an xml
<CommonTestData>
<GiftCards>
<GiftCard>
<cardnumber>7777016774730834</cardnumber>
<number>1815</number>
</GiftCard>
<GiftCard>
<cardnumber>7777016774687937</cardnumber>
<number>6256</number>
</GiftCard>
</GiftCards>
I have to iterate these xml and read values and enter into an Selenium web application and check whether gift card applied amount is greater than zero . If the amount applied is zero then try another card . If the amount applied is greater than zero then break the loop
My code something look like
for (int i=0;i<xmlvalue.getNodeCount("GiftCard", "CommonTestData.xml");i++){
//giftcardaccordian.click();
giftcardnumber.sendKeys(xmlvalue.getValue("cardnumber"+i, "GiftCard", "CommonTestData.xml")); // I need code for getvalue function so that i can iterate through
giftcardpin.sendKeys(xmlvalue.getValue("cardnumber"+i, "GiftCard", "CommonTestData.xml"));
giftcardapplybutton.click();
try{
if(appliedgiftcardamount.getText()!="$0"){
break;
}
}catch (Exception e ){
Assert.fail("Cannot apply reward certicate");
}
}
I need implementaion for Getvalue so that i can iterate through. Right now my implementation is something like
public String getValue(String csstagname, String Elementname, String xmlfilename) {
String eElement1;
try {
String path = "config/XML/" + xmlfilename;
File fXmlFile = new File(path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName(Elementname);
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
eElement1 = csstagname;
Element eElement2 = (Element) nNode;
value = (getTagValue(eElement1, eElement2));
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return (value);
}
}
What you are doing is possible, but it's not in the spirit of XML. Do you control the XML file? Change the format so that card nnumber and number have their own overarching tag to bind them together:
<CommonTestData>
<GiftCards>
<GiftCard>
<cardnumber>7777016774730834</cardnumber>
<number>1815</number>
</GiftCard>
<GiftCard>
<cardnumber>7777016774687937</cardnumber>
<number>6256</number>
</GiftCard>
</GiftCards>
</CommonTestData>
If you do not control the format, extract all nodes tagged with cardnumber, all nodes tagged with number, then access both arrays with same index.

navigating hierarchy of xml input file

How do I list the element names at a given level in an xml schema hierarchy? The code I have below is listing all element names at every level of the hierarchy, with no concept of nesting.
Here is my xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="CDA.xsl"?>
<SomeDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:something">
<title>some title</title>
<languageCode code="en-US"/>
<versionNumber value="1"/>
<recordTarget>
<someRole>
<id extension="998991"/>
<addr use="HP">
<streetAddressLine>1357 Amber Drive</streetAddressLine>
<city>Beaverton</city>
<state>OR</state>
<postalCode>97867</postalCode>
<country>US</country>
</addr>
<telecom value="tel:(816)276-6909" use="HP"/>
</someRole>
</recordTarget>
</SomeDocument>
Here is my java method for importing and iterating the xml file:
public static void parseFile() {
//get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
//parse using builder to get DOM representation of the XML file
Document dom = db.parse("D:\\mypath\\somefile.xml");
//get the root element
Element docEle = dom.getDocumentElement();
//get a nodelist of elements
NodeList nl = docEle.getElementsByTagName("*");
if (nl != null && nl.getLength() > 0) {
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("node.getNodeName() is: "+node.getNodeName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
The output of the above program is:
title
languageCode
versionNumber
recordTarget
someRole
id
addr
streetAddressLine
city
state
postalCode
country
telecom
Instead, I would like to output the following:
title
languageCode
versionNumber
recordTarget
It would be nice to then be able to list the children of recordTarget as someRole, and then to list the children of someRole as id, addr, and telecom. And so on, but at my discretion in the code. How can I change my code to get the output that I want?
You're getting all nodes with this line:
NodeList nl = docEle.getElementsByTagName("*");
Change it to
NodeList nl = docEle.getChildNodes();
to get all of its children. Your print statement will then give you the output you're looking for.
Then, when you iterate through your NodeList, you can choose to call the same method on each Node you create:
NodeList children = node.getChildNodes();
If you want to print an XML-like structure, perhaps a recursive method that prints all child nodes is what you are looking for.
You could re-write the parseFile (I'd rather call it parseChildrenElementNames) method to take an input String that specifies the element name for which you want to print out its children element names:
public static void parseChildrenElementNames(String parentElementName) {
// get the factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
// Using factory get an instance of document builder
DocumentBuilder db = dbf.newDocumentBuilder();
// parse using builder to get DOM representation of the XML file
Document dom = db
.parse("D:\\mypath\\somefile.xml");
// get the root element
NodeList elementsByTagName = dom.getElementsByTagName(parentElementName);
if(elementsByTagName != null) {
Node parentElement = elementsByTagName.item(0);
// get a nodelist of elements
NodeList nl = parentElement.getChildNodes();
if (nl != null) {
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println("node.getNodeName() is: "
+ node.getNodeName());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
However, this will only consider the first element that matches the specified name.
For example, to get the list of elements under the first node named someRole, you would call parseChildrenElementNames("someRole"); which would print out:
node.getNodeName() is: id
node.getNodeName() is: addr
node.getNodeName() is: telecom

How to read a generic XML file in java

I'm looking for ways to read a generic xml file
Here is an example of a normal xml file
<?xml version="1.0"?>
<students>
<student>
<name>John</name>
<grade>B</grade>
<age>12</age>
</student>
<student>
<name>Mary</name>
<grade>A</grade>
<age>11</age>
</student>
<student>
<name>Simon</name>
<grade>A</grade>
<age>18</age>
</student>
</students>
and here is example of a typical xml parser that would read that code and print it out
public class XMLParser {
public void getAllUserNames(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(fileName);
if (file.exists()) {
Document doc = db.parse(file);
Element docEle = doc.getDocumentElement();
// Print root element of the document
System.out.println("Root element of the document: "
+ docEle.getNodeName());
NodeList studentList = docEle.getElementsByTagName("student");
// Print total student elements in document
System.out
.println("Total students: " + studentList.getLength());
if (studentList != null && studentList.getLength() > 0) {
for (int i = 0; i < studentList.getLength(); i++) {
Node node = studentList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out
.println("=====================");
Element e = (Element) node;
NodeList nodeList = e.getElementsByTagName("name");
System.out.println("Name: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("grade");
System.out.println("Grade: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("age");
System.out.println("Age: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
}
}
} else {
System.exit(1);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
XMLParser parser = new XMLParser();
parser.getAllUserNames("c:\\test.xml");
}
}
This code needs lines like this
NodeList studentList = docEle.getElementsByTagName("student");
NodeList nodeList = e.getElementsByTagName("name");
In order to work correctly.
My questions comes from how would I make that generic. Is there any way where I could read that same XML file without having to get specific elements by tagNames and yet still print it out in a view able format.
In the above example you are using Dom parser. By using Jaxb Context unmarshaller you can convert the xml to java object, then you can achive your task.
You need to have a generic function to handle.
Generic function is as follows:
/* Prints the Node Value */
public void PrintNodeValue(Element element, String tagName, String msg)
{
NodeList nodeList = element.getElementsByTagName(tagName);
System.out.println(msg + nodeList.item(0).getChildNodes().item(0).getNodeValue());
}
Function is called as below:
PrintNodeValue(e, "name", "Name: ");
PrintNodeValue(e, "grade", "Grade: ");

Read values from a complex xml using java

HI I am new to Java and trying to read an XML file.
Here is my XML file :-
<?xml version="1.0" encoding="UTF-8"?>
<parameter>
<attribute>a</attribute>
Here is my code I am trying to read the key and value from the xml but I am stuck .Here is my code :-
public class TestDBMain {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File file = new File("ACL.xml");
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbfactory.newDocumentBuilder();
Document doc = builder.parse(file);
NodeList nList = doc.getElementsByTagName("testCaseDataName");
for(int i = 0;i<nList.getLength();i++){
Node nNode = nList.item(i);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
Element ele = (Element) nNode;
// System.out.println(ele.getTextContent());
//System.out.println(ele.getElementsByTagName("testCaseName").item(0).getTextContent());
System.out.println(ele.getAttributeNode("testCaseDataName"));
//I dont know which methods to use to print the key and value in the xml under parameter
}
}
}
}
Can anyone please help me with this
Disclaimer: I maintain the JDOM project, so I am biased.... but... this is an ideal use case for JDOM:
Document doc = new SAXBuilder().build(new File("ACL.xml"));
Element root = doc.getRootElement();
for (Element testcase : root.getChildren()) {
int id = Integer.parseInt(testcase.getChildText("id"));
String name = testcase.getChildText("testCaseName");
String expect = testcase.getChildText("expectedResult");
Map<String,String> params = new LinkedHashMap<String,String>();
Element parmemt = testcase.getChild("parameter");
if (parmemt != null) {
Iterator<Element> it = parmemt.getChildren().iterator();
while (it.hasNext()) {
Element key = it.next();
if (!"key".equals(key.getName())) {
throw new IllegalStateException("Expected key but got " + key);
}
if (!it.hasNext()) {
throw new IllegalStateException("Expected value for key " + key);
}
Element val = it.next();
if (!"value".equals(val.getName())) {
throw new IllegalStateException("Expected value but got " + val);
}
params.put(key.getValue(), val.getValue());
}
}
System.out.printf("Processing test case %d -> %s\n Expect %s\n Parameters: %s\n",
id, name, expect, params.toString());
}
For me this produces the output
Processing test case 1 -> EditTest
Expect nooptionsacltrue
Parameters: {}
Processing test case 2 -> AddTest
Expect featuresaddedacltrue
Parameters: {featues=w,f}
Processing test case 3 -> AddTest
Expect duplicateacltrue
Parameters: {projectType=NEW, Name=28HPM, status=ACTIVE, canOrder=Yes}
your code read <testCaseDataName> node. it is not go inside of this tag.
so try this..
for(int i = 0;i<nList.getLength();i++){
NodeList nodeList = nList.item(i).getChildNodes();
for(int j = 0;j<nList.getLength();j++){
Node nNode = nodeList.item(j);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
System.out.println(nNode.getNodeName() +" : "+nNode.getTextContent());
if(nNode.getNodeName().equals("parameter")){
NodeList param = nNode.getChildNodes();
System.out.println(" "+param.item(0).getNodeName() +" : "+param.item(0).getTextContent());
System.out.println(" "+param.item(1).getNodeName() +" : "+param.item(1).getTextContent());
}
}
}
}

how to get attribute of given node?

I am trying to write DOM XML parsing.
My Xml file
<?xml version="1.0"?>
<BLAH>
<AgentNm type="citi1">
<accName>accName1</accName>
<accType>accType1</accType>
<someThing>someThing1</someThing>
<amt>100000</amt>
</AgentNm>
<AgentNm type="citi2">
<accName>accName2</accName>
<accType>accType2</accType>
<someThing>someThing2</someThing>
<amt>200000</amt>
</AgentNm>
</BLAH>
And i tried following java code
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse (new File("c:\\file.xml"));
// normalize text representation
doc.getDocumentElement ().normalize ();
System.out.println ("Root element of the doc is " +doc.getDocumentElement().getNodeName());
NodeList agentNm = doc.getElementsByTagName("AgentNm");
int totalAgentNm = agentNm.getLength();
System.out.println("Total no of Agents : " + totalAgentNm);
for(int s=0; s<agentNm.getLength() ; s++){
Node firstPersonNode = agentNm.item(s);
if(firstPersonNode.getNodeType() == Node.ELEMENT_NODE){
Element firstPersonElement = (Element)firstPersonNode;
PrintNodeElem(firstPersonElement,"type");
}//end of if clause
}//end of for loop with s var
static void PrintNodeElem(Element nodeElem,String elem){
NodeList someThingList = nodeElem.getElementsByTagName(elem);
Element ageElement = (Element)someThingList.item(0);
NodeList textAgeList = ageElement.getChildNodes();
System.out.println(elem+" : " +((Node)textAgeList.item(0)).getNodeValue().trim());
}
But, when i tried to execute above method,
i am getting null pointer exception.
can any one explain me, how to fix this.
if you want an attribute of a given node, I would suggest XPath. It is much easier.
http://onjava.com/onjava/2005/01/12/xpath.html

Categories