navigating hierarchy of xml input file - java

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

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.

XML - Extract One tag Value

I have to extract tag value from an xml Document that contains a single tag like below:
<error>Permission denied</error>
i have tried:
String xmlRecords = "<error>Permission denied</error>"
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlRecords));
Document doc = db.parse(is);
Node nodes = doc.getFirstChild();
String = nodes.getNodeValue();
but it dont works.
How can i do it ?
Use doc.getDocumentElement().getTextContent() to get the string Permission denied.
With DOM it´s util to know the structure of the XML document, and which node level are you looking for.
After get Document, you can use document.getElementsByTagName("root") to look for the root or father tags, and get the childs as a list to look for the item. Something like this:
NodeList listresults = document.getElementsByTagName('father/root element string');
NodeList nl = listresults.item(0).getChildNodes();
// Recorremos los nodos
for (int temp = 0; temp < nl.getLength(); temp++) {
Node node = nl.item(temp);
// Check if it is a node
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if(element.getNodeName().equals("error")){
// check the element
}
}
}
I hope this helps you.
just try following code.
String value = nodes.getTextContent();
You have to construct the string if you are using the above approach. You will get the string values of the tag name and content using the functions.
Tag name = nodes.getTextContent()
tag value = nodes.getLocalName()
I guess this is what you want
Element element = document.getDocumentElement();
NodeList errorTagList = element.getElementsByTagName("error");
if (errorTagList != null && errorTagList.getLength() > 0) {
NodeList errorTagSubList = errorTagList.item(0).getChildNodes();
if (errorTagSubList != null && errorTagSubList.getLength() > 0) {
String value = errorTagSubList.item(0).getNodeValue();
}
}

Retrieving different child elements xml

I have a xml file that looks like this.
<Device>
<Staff>
<Name>ABC</Name>
<Name>Hello</Name>
</Staff>
<Connect>
<Speed>123</Speed>
<Speed>456</Speed>
</Connect>
</Device>
I need help in retrieving the value of name & speed as i have never tried xml before. I am getting null pointer exception whenever I try to retrieve the element values. Any help is appreciated.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// Load the input XML document, parse it and return an instance of the
// Document class.
Document document = builder.parse(new File("C:/Users/AA/Desktop/eclipse/lol/testing.xml"));//change to own directory
NodeList nodeList = document.getDocumentElement().getChildNodes();
System.out.println(nodeList.getLength());
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(i);
Element elem = (Element) node;
// Get the value of the ID attribute.
// String ID = node.getAttributes().getNamedItem("ID").getNodeValue();
// Get the value of all sub-elements.
String name = elem.getElementsByTagName("Name")
.item(0).getChildNodes().item(0).getNodeValue();
Integer speed = Integer.parseInt(elem.getElementsByTagName("Connect")
.item(0).getChildNodes().item(0).getNodeValue());//null pointer exception happens here
staffList.add(new staff(name));
connectList.add(new connect(speed));
}
}
// Print all employees.
for (staff stl : staffList)
{System.out.println("STAFF "+stl.getName());}
for (connect ctl : connectList)
{System.out.println("Connect "+ctl.getSpeed());}
You will have null pointer exceptions because you're assuming that in every iteration of the for loop, the desired nodes have children elements:
String name = elem.getElementsByTagName("Name")
.item(0).getChildNodes().item(0).getNodeValue();
In the above code, you are accessing the first child of a Name element which is a text node (e.g. ABC), and then getting its children nodes, which will cause an exception since there no children elements inside the text node.
Likewise,
Integer speed = Integer.parseInt(elem.getElementsByTagName("Connect")
.item(0).getChildNodes().item(0).getNodeValue());
will cause an exception in one of the iterations of the loop where elem corresponds to Connect itself.
You can try the following code instead:
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(i);
Element elem = (Element) node;
// Get the value of the ID attribute.
// String ID =
// node.getAttributes().getNamedItem("ID").getNodeValue();
// Get the value of all sub-elements.
NodeList nameNodes = elem.getElementsByTagName("Name");
for(int j = 0; j < nameNodes.getLength(); j++) {
Node nameNode = nameNodes.item(j);
staffList.add(new staff(nameNode.getTextContent()));
}
NodeList speedNodes = elem.getElementsByTagName("Speed");
for(int j = 0; j < speedNodes.getLength(); j++) {
Node speedNode = speedNodes.item(j);
connectList.add(new connect(Integer.parseInt(speedNode.getTextContent())));
}
}
P.S.: Try to use class names that start with an uppercase.
You want getTextContent() rather than getNodeValue() - the latter always returns null for element nodes.
See: DOMDocument getNodeValue() returns null (contains an output escaped string)

Getting Element (not Node) below root in Java DOM (XML parser)

I need to get the tag of an element right below the root, but DOM seems only to offer methods getting child nodes (not elements) and you cant cast from one to the other.
http://ideone.com/SUjRmn
#Override
public void loadXml(String filepath) throws Exception {
File f = new File(filepath);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
Document doc = null;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
try {
doc = db.parse(f);
} catch (SAXException | IOException | NullPointerException e) {
e.printStackTrace();
}
Element root = doc.getDocumentElement();
Node firstChild = root.getFirstChild();
String tag = firstChild.getNodeName();
//here is the problem. I can't cast from Node to Element and Node
//stores only an int value, not the name of the object I want to restore
ShapeDrawer drawable = null;
switch (tag) {
case "scribble":
drawable = new ScribbleDrawer();
...
From the class to restore:
#Override
public void setValues(Element root) {
NodeList nodelist = null;
nodelist = root.getElementsByTagName("color");
colorManager.setColor((nodelist.item(0).getTextContent()));
this.color = colorManager.getCurrentColor();
System.out.println(color.toString());
nodelist = root.getElementsByTagName("pressx");
pressx = Integer.parseInt(nodelist.item(0).getTextContent());
System.out.println(pressx);
nodelist = root.getElementsByTagName("pressy");
pressy = Integer.parseInt(nodelist.item(0).getTextContent());
System.out.println(pressy);
nodelist = root.getElementsByTagName("lastx");
lastx = Integer.parseInt(nodelist.item(0).getTextContent());
nodelist = root.getElementsByTagName("lasty");
lasty = Integer.parseInt(nodelist.item(0).getTextContent());
}
public void toDOM(Document doc, Element root) {
System.out.println("ScribbleDrawer being saved");
Element shapeBranch = doc.createElement("scribble");
Attr attr1 = doc.createAttribute("hashcode");
attr1.setValue(((Integer) this.hashCode()).toString());
shapeBranch.setAttributeNode(attr1);
root.appendChild(shapeBranch);
Element eColor = doc.createElement("color");
eColor.setTextContent(colorManager.namedColorToString(color));
shapeBranch.appendChild(eColor);
// creating tree branch
Element press = doc.createElement("press");
Attr attr2 = doc.createAttribute("pressx");
attr2.setValue(((Integer) pressy).toString());
press.setAttributeNode(attr2);
Attr attr3 = doc.createAttribute("pressy");
attr3.setValue(((Integer) pressy).toString());
press.setAttributeNode(attr3);
shapeBranch.appendChild(press);
Element last = doc.createElement("last");
Attr attr4 = doc.createAttribute("lastx");
attr4.setValue(((Integer) lastx).toString());
last.setAttributeNode(attr4);
Attr attr5 = doc.createAttribute("lasty");
attr5.setValue(((Integer) lasty).toString());
last.setAttributeNode(attr5);
shapeBranch.appendChild(last);
}
I know other parsers are easier, but I am almost finished and when it comes to polymorphy JAXB seems to be just as complicated with Option-marshalling etc
EDIT: this is what the xml looks like; instead of "scribble" other tags/polymorphic children are possible which are deserialized from different instance variables (and thus different DOM-trees except for the root)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Drawables>
<scribble hashcode="189680059">
<color>Black</color>
<press pressx="221" pressy="221"/>
<last lastx="368" lasty="219"/>
</scribble>
<scribble hashcode="1215837841">
<color>Black</color>
<press pressx="246" pressy="246"/>
<last lastx="368" lasty="221"/>
</scribble>
If your node is an Element, you can cast it from node to element. But your first child might also be a text node, which can't be cast, of course. You have to test the nodes for their NodeType before casting.
If your XML is not using namespaces, you can use a method like this one to extract your child elements. It receives a list of nodes, test each one and returns a list containing only the elements:
public static List getChildren(Element element) {
List<Element> elements = new ArrayList<>();
NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
elements.add((Element) node);
}
}
return elements;
}
An alternative is to use an API which already includes such utility methods, like DOM4J, or JDOM.

Child node name in a xml

I am trying to write a piece of code that can parse any xml and print its contents. I am using DOM parser. I am able to get the name of the root tag of the xml, but cant obtain tag name of the immediate child. This can be done easily in case the node names are known by using the method 'getElementsByTagName' . Is there any way out of this dilemma ?
My code goes like this :
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
doc.getDocumentElement().normalize();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
doc.getDocumentElement().getNodeName() // this gets me the name of the root node.
Now how can i get the name of the immediate child node so that i can traverse the xml using getElementsByTagName("x").
Thanks in advance.
getChildNodes() returns all children of an element. The list will contain more then just elements so you'll have to check each child node if it is an element:
NodeList nodes = doc.getDocumentElement().getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.get(i);
if (node instanceof Element) {
Element childElement = (Element) node;
System.out.println("tag name: " + childElement.getTagName());
}
}

Categories