Java - Delete child node from dynamic XML - java

I want to delete a XML node that contains a PDF in Base64. This is an example:
<?xml version="1.0" encoding="UTF-8"?>
<getResult>
<id>null</id>
<pdf>ioje98fh23fjkiwf72322342</pdf>
</getResult>
First, I transform the XML in String to Document but the result is null. This is my code:
DocumentBuilder dbf = null;
Document doc = null;
try {
dbf = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader("<getResult><id>null</id><pdf>ioje98fh23fjkiwf72322342</pdf></getResult>"));
doc = dbf.parse(is);
NodeList children = doc. getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node currentChild = children.item(i);
System.out.println(currentChild);
}
} catch (Exception e) {
System.out.println(e.getMessage().toString());
}
The result is always: [getResult: null]
Considering that the main node can vary but the structure does not, How can I get the PDF node?

Here is the could you could use to retrieve the data.
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.w3c.dom.CharacterData;
public class LabFour {
public static void main(String[] args) {
DocumentBuilder dbf = null;
Document doc = null;
try {
dbf = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(
new StringReader("<getResult><id>null</id><pdf>ioje98fh23fjkiwf72322342</pdf></getResult>"));
doc = dbf.parse(is);
NodeList nodes = doc.getElementsByTagName("getResult");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList name = element.getElementsByTagName("id");
Element line = (Element) name.item(0);
System.out.println("id: " + getCharacterDataFromElement(line));
NodeList pdf = element.getElementsByTagName("pdf");
line = (Element) title.item(0);
System.out.println("pdf: " + getCharacterDataFromElement(pdf));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
}

SimpleXml can do it:
final SimpleXml simple = new SimpleXml();
final Element element = simple.fromXml(data);
element.children.remove(1);
System.out.println(simple.domToXml(element));
Will output:
<getResult><id>null</id></getResult>
From maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.4.0</version>
</dependency>

Related

Store xml value as a Map using XPATH using JAVA

I am using XPATH to parse xml document,please find the xml below
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<bookEvent>
<bookName>harry_potter</bookName>
<bookEntity>comic</bookEntity>
<bookEntityId>10987645</bookEntityId>
<bookParameter>
<name>Name1</name>
<value>value1</value>
</bookParameter>
<bookParameter>
<name>Name2</name>
<value>value2</value>
</bookParameter>
<bookParameter>
<name>Name3</name>
<value>value3</value>
</bookParameter>
<bookParameter>
<name>Name4</name>
<value>value4</value>
</bookParameter>
<bookParameter>
<name>Name5</name>
<value>value5</value>
</bookParameter>
</bookEvent>
</soap:Body>
</soap:Envelope>
Here I would like to convert BookParameters to Map like below
{"Name1":"value1","Name2":"value2" etc}
I have tried the below code and i can get a Map but not in the expected format,
try{
Map<String,String> eventParameters = new HashMap<>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("book.xml");
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
NodeList nodeList = (NodeList)xpath.compile("//bookEvent//eventParameter").evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if(node.hasChildNodes()) {
NodeList childNodes = node.getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
Node childNode = childNodes.item(j);
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(childNode.getNodeName()+"::"+childNode.getNodeValue()+"::"+childNode.getTextContent());
eventParameters.put(childNode.getTextContent(),childNode.getTextContent());
}
}
}
}
System.out.println("print map::"+eventParameters);
} catch (Exception e) {
e.printStackTrace();
}
The output looks like this
print map::{Name3=Name3, Name4=Name4, value5=value5, Name5=Name5, value2=value2, value1=value1, value4=value4, value3=value3, Name1=Name1, Name2=Name2}
Please somebody guide me to create a below map from the xml,Any help would be appreciable.
{"Name1":"value1","Name2":"value2" etc}
You can do it as a one-liner in XPath 3.1:
map:merge(//bookParameter!map{string(name): string(value)})
=> serialize(map{'method':'json'})
You can run XPath 3.1 from Java by installing Saxon-HE 9.8 (open source)
Use Below code :
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ReadXMLFile {
public static Map<String,String> hMap = new LinkedHashMap<>();
public static void main(String argv[]) {
try {
File fXmlFile = new File("C:\\Users\\jaikant\\Desktop\\QUESTION.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("bookParameter");
for (int parameter = 0; parameter < nodeList.getLength(); parameter++) {
Node node = nodeList.item(parameter);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) node;
String name = eElement.getElementsByTagName("name").item(0).getTextContent();
String value = eElement.getElementsByTagName("value").item(0).getTextContent();
hMap.put(name, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
hMap.forEach((h,k) -> {
System.out.println(h + ":" + k);
});
}
}
It will print exactly what you are looking for.

Modifying value of a particular tag in xml

I have an xml as follows
<?xml version="1.0" encoding="ISO-8859-1"?><TXNEXP FileDate="2017-05-23" FileName="/cortex/tsd/out/OPTSKRtxnexp20170523.xml" Instcode="SKR" TotNumTxns="74330">
<AUTHADV>
<LOCALDATE>2017-05-22</LOCALDATE>
<LOCALTIME>200011</LOCALTIME>
<PAN>336890380<PAN>
</AUTHADV>
<AUTHREV>
<LOCALDATE>2017-05-22</LOCALDATE>
<LOCALTIME>200011</LOCALTIME>
<PAN>336890380<PAN>
</AUTHREV>
<FINAL>
<LOCALDATE>2017-05-22</LOCALDATE>
<LOCALTIME>200011</LOCALTIME>
<PAN>336890380<PAN>
</FINAL>
</TXNEXP>
Now, I am modifying the value of PAN tag and writing it back to the xml but I am not able to do so for all the PAN tags.
Here is what I am doing.
NodeList node = doc.getElementsByTagName("TXNEXP");
Element emp = null;
for (int i = 0; i < node.getLength(); i++) {
emp = (Element) node.item(i);
Node name = emp.getElementsByTagName("PAN").item(0).getFirstChild();
//Modifying the tag
}
From the above code only PAN under AUTHADV tag gets modified and the rest two values don't change.
How can I ensure all the PAN tags to get modified ?
This is not the prettiest solution but after you fix the missing slash in the PAN closing tags this will work.
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
class Extract {
public static void main(String[] args) {
try {
File fXmlFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
NodeList topNodes = doc.getElementsByTagName("TXNEXP");
for (int i = 0; i < topNodes.getLength(); i++) {
NodeList middleNodes = topNodes.item(i).getChildNodes();
for (int j = 0; j < middleNodes.getLength(); j++) {
try {
NodeList theNodes = ((Element)middleNodes.item(j)).getElementsByTagName("PAN");
System.out.println(theNodes.item(0).getFirstChild().getNodeValue());
if (j == 1) {
// modify a value
theNodes.item(0).getFirstChild().setNodeValue("4567");
System.out.println(theNodes.item(0).getFirstChild().getNodeValue());
}
} catch (ClassCastException e) {}
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}
For a slightly better approach you could use XPaths.
import javax.xml.xpath.*;
class Extract {
public static void main(String[] args) {
try {
File fXmlFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xpath.evaluate("/TXNEXP/*/PAN", doc, XPathConstants.NODESET);
for (int n = 0; n < nodes.getLength(); n++) {
System.out.println(nodes.item(n).getFirstChild().getNodeValue());
if (n == 1) {
nodes.item(n).getFirstChild().setNodeValue("4567");
System.out.println(nodes.item(n).getFirstChild().getNodeValue());
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}

How to print child tag name of select parent tag using Single Java Method?

I need to print Child tag name of select parent tag using Java Method. In this given below Xml File. I am going select a parent tag subject and I am going to print each and every child and SubChild Tag inside subject parent tag.Example: div,p,LiberaryBook,p,p,textfile,textfile,textfile. 2. And it should print the text inside p tag which contain textfile tag
1. How to print the child tag name from select parent tag? and print the How to print text inside p tag which contain textfile tag?
<parent>
<Body class="student" id="181_student_method_3">
<Book class="Book_In_School_11" id="181_student_method_11"/>
<subject class="subject_information " id="181_student_subject_12"/>
<div class="div_passage " id="181_div_method_3">
<p class=" p_book_name" id="181_paragraph_13">
Best Java
<LiberaryBook class="Liberary" id="181_Liberary_9" >
<span class="p_span_name" id="181_span_13">Hello</span>
</LiberaryBook>
Java Program
</p>
<p class=" p_book_name" id="181_paragraph_13">
World
</p>
<p class="p_book_name" id="181_paragraph_14">
<textfile class="choice" id="C_10">Java.</textfile>
<textfile class="choice" id="C_11">
Find out how you rate against top coders.
</textfile>
<textfile class="choice3 " id="choice_12">
Unlock awesome startup jobs and hacker deals.
</textfile>
<textfile class="choice4 " id="choice_13">
User Id friends.
</textfile>
</p>
</div>
</subject>
</Body>
</parent>
private static void deleteElement(Document someNode) {
NodeList parentNode = someNode.getElementsByTagName("hottextInteraction").item(0).getChildNodes();
int parentNodeContentSize = parentNode.getLength();
for (int i = 0; i < parentNodeContentSize; i++) {
Node parentNodeitem = parentNode.item(i);
System.out.println("ChildList"+((Node) parentNodeitem.getChildNodes()).getNodeName());
NamedNodeMap attributes = parentNodeitem.getAttributes();
String attributeInParent = attributes != null ? (attributes
.getNamedItem("class") != null ? attributes.getNamedItem(
"class").getNodeValue().trim() : null) : null;
if (attributeInParent != null && attributeInParent.equals("div_passage")) {
NodeList stemContent = parentNodeitem.getChildNodes();
for(int j=0;j<stemContent.getLength();j++){
Node stem = stemContent.item(j);
if(stem instanceof Element && (stem.getNodeName().equals("p"))){
NodeList parentNode1 = someNode.getElementsByTagName("p");//First try.item(0).getChildNodes();
int parentNodeContentSize1 = parentNode1.getLength();
System.out.println(parentNodeContentSize1);
for (int i1 = 0; i1 < parentNodeContentSize1;) {
Node node = parentNode1.item(i1);
if (node instanceof Element) {
Element childElement = (Element) node;
System.out.println("tag name: " + childElement.getTagName());
}i1++;
System.out.println("Sub Child Tag:"+node.getFirstChild().getNodeName());*/
}
}
}
}
}
}
Please Check with this code to get Child Tag name and get it's text content inside P tag
package com.video.convertor;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Hottext {
public static void main(String[] args) {
String filePath = "/Users/myXml/check/test.xml";
File xmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
try {
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
//Element root = doc.getDocumentElement();
System.out.println(deleteElement(doc));
doc.getDocumentElement().normalize();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("/Users/myXml/DEMO4.xml"));
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, result);
System.out.println("XML file updated successfully");
} catch (SAXException | ParserConfigurationException | IOException | TransformerException e1) {
e1.printStackTrace();
}
}
private static String deleteElement(Document someNode) {
String contents = "";
NodeList itemBody = someNode.getElementsByTagName("subject").item(0).getChildNodes();
int itemBodyContentSize = itemBody.getLength();
for (int i = 0; i < itemBodyContentSize; i++) {
Node passage = itemBody.item(i);
NamedNodeMap attributes = passage.getAttributes();
String selectText = attributes != null ? (attributes
.getNamedItem("class") != null ? attributes.getNamedItem(
"class").getNodeValue() : null) : null;
if (selectText != null && selectText.toString().trim().equals("div_passage")) {
NodeList pasageElements = passage.getChildNodes();
int length = pasageElements.getLength();
boolean isPassageContent = false;
for(int j=0;j<length;j++){
Node passageContent = pasageElements.item(j);
if(passageContent instanceof Element && (passageContent.getNodeName().equals("p"))){
if(isPassageContent){
NodeList p = pasageElements.item(j).getChildNodes();
for (int k = 0;k < p.getLength(); k++){
Node noded = p.item(k);
if (noded.getNodeType() == Node.ELEMENT_NODE) {
if(noded.getNodeName() != null && (noded.getNodeName().equals("textfile"))){
contents = contents+p.item(k).getTextContent()+"\n";
}
}
}
}else{
isPassageContent = true;
}
}
}
}
}return contents;
}
}

Parsing XML attributes from Complex Empty Elements

I have an xml file in the following pattern which contains a few Complex Empty Elements(elements with no content, only attributes).
<items>
<item id="0" name="a" />
<item id="1" name="b" />
</items>
I'm at lose to parse the attributes from them. This is what I have done so far :
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(inputStream);
Element itemsElement = document.getDocumentElement();
if (itemsElement.getTagName().equals(TAG_ITEMS)) {
NodeList nodeList = itemsElement.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
// process each item node
Node node = nodeList.item(i);
if (node.getNodeType() == Node.TEXT_NODE) { // Is this the right way?
Text text = (Text) node;
// Do stuff with attributes
}
}
}
I cannot cast these Text nodes to Element nodes and get attributes, I cannot get attributes from node using getAttributes - NPE at NamedNodeMap attributes.getLength(), I cannot cast it to Text and get attributes. How can I parse the attributes?
You are not interested in the text context of the nodes inside of items but in the attributes of the nodes item. you could proceed as follow:
//process each item node
Node node = nodeList.item(i);
if (node.getNodeName().equals("item")) {
NamedNodeMap attributes = node.getAttributes();
System.out.printf("id=%s, name=%s%n",
attributes.getNamedItem("id").getTextContent(),
attributes.getNamedItem("name").getTextContent());
}
This would print:
id=0, name=a
id=1, name=b
Assuming you want to get the indiviudal attributes of the nodes you need to one of two things (or both depending on your needs)...
You need to test if the current node is an ELEMENT_NODE or if the current node's name is equal to item (assuming all the node names are the same), for example...
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
public class Test {
public static final String TAG_ITEMS = "items";
public static void main(String[] args) {
try (InputStream is = Test.class.getResourceAsStream("/Test.xml")) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(is);
Element itemsElement = document.getDocumentElement();
if (itemsElement.getTagName().equals(TAG_ITEMS)) {
NodeList nodeList = itemsElement.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
NamedNodeMap attributes = node.getAttributes();
Node idAtt = attributes.getNamedItem("id");
Node nameAtt = attributes.getNamedItem("name");
System.out.println("id = " + idAtt.getNodeValue());
System.out.println("name = " + nameAtt.getNodeValue());
}
}
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
Which will output...
id = 0
name = a
id = 1
name = b
All of this could be greatly reduced by using XPath, for example, if all the item nodes are the same name, then you could just use
/items/item
As the query. If the node names are different, but the attributes are the same, then you could use
/items/*[#id]
which will list all the nodes under items which has an id attribute, or
/items/*[#name]
which will list all the nodes under items which has an name attribute...
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Test {
public static void main(String[] args) {
try (InputStream is = Test.class.getResourceAsStream("/Test.xml")) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(is);
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xpath.compile("/items/item");
NodeList nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
expression = xpath.compile("/items/*[#id]");
nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
expression = xpath.compile("/items/*[#name]");
nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
process(nodes);
} catch (Exception exp) {
exp.printStackTrace();
}
}
protected static void process(NodeList nodes) {
for (int index = 0; index < nodes.getLength(); index++) {
Node item = nodes.item(index);
NamedNodeMap attributes = item.getAttributes();
Node idAtt = attributes.getNamedItem("id");
Node nameAtt = attributes.getNamedItem("name");
System.out.println("id = " + idAtt.getNodeValue() + "; name = " + nameAtt.getNodeValue());
}
}
}

Parsing XML using java DOM

Im new in Java, and i have a task to Parse one xml file using http with current url http://belbooner.site40.net/testXmls/details.xml
I created Some class to parse it using Dom method, but im having java.lang.NullPointerException while trying to get one Nodes value
So here's the code
import java.security.KeyStore.Builder;
import java.util.*;
import java.io.*;
import java.net.*;
import javax.swing.text.Document;
import javax.xml.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.*;
import org.w3c.dom.CharacterData;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class RequestResponse {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
RequestResponse req= new RequestResponse();
req.getHTTPXml(url);
}
void getHTTPXml(URL url) throws ParserConfigurationException, IOException, SAXException {
//URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("ACCEPT","application/xml");
InputStream xml = conn.getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(xml);
System.out.println(document);
String doctype = conn.getContentType();
System.out.print(doctype);
NodeList root = document.getChildNodes();
Node server = getNodes("server",root);
Node check = getNodes("check", server.getChildNodes());
NodeList nodes = check.getChildNodes();
String checkid= getNodeValue("checkid", nodes);
System.out.println(checkid);
conn.disconnect();
//return (Document) DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xml);
}
Node getNodes(String tagName, NodeList nodes) {
for(int i=0; i< nodes.getLength();i++) {
Node node= nodes.item(i);
if(node.getNodeName().equalsIgnoreCase(tagName)) {
return node;
}
}
return null;
}
String getNodeValue(String tagName, NodeList nodes ) {
for ( int i = 0; i < nodes.getLength(); i++ ) {
Node node = nodes.item(i);
if (node.getNodeName().equalsIgnoreCase(tagName)) {
NodeList childNodes = node.getChildNodes();
for (int y = 0; y < childNodes.getLength(); y++ ) {
Node data = childNodes.item(y);
if ( data.getNodeType() == Node.TEXT_NODE ) {
return data.getNodeValue();
}
if(data instanceof CharacterData) {
CharacterData cd= (CharacterData) data;
return cd.getData();
}
}
}
}
return "";
}
}
The stacktrace I'm getting is the following:
application/xmlException in thread "main" java.lang.NullPointerException at
RequestResponse.getHTTPXml(RequestResponse.java:45) at
RequestResponse.main(RequestResponse.java:22)
After changin Node server = getNodes("server",root); to `
Node resultNode = getNodes("result", root);
Node server = getNodes("server", resultNode.getChildNodes());`
`application/xmlException in thread "main" java.lang.NullPointerException
at RequestResponse.getHTTPXml(RequestResponse.java:49)
at RequestResponse.main(RequestResponse.java:22)
`
Please help me to find the issue.
The problem is that Node server = getNodes("server",root); is returning null.
Why does this happen? Well look how you implemented getNodes
Node getNodes(String tagName, NodeList nodes) {
for(int i=0; i< nodes.getLength();i++) {
Node node= nodes.item(i);
if(node.getNodeName().equalsIgnoreCase(tagName)) {
return node;
}
}
return null;
}
You are giving as input the document root which is a single "Result" node, you iterate through it and you compare if the node's name is in this case "server" which never will be, hence you return null and get a NPE.
Your node look up must be done in the following way:
NodeList root = document.getChildNodes();
// Keep in mind that you have the following structure:
// result
// server
// checks
// check
// checkId
// check
// checkId
Node resultNode = getNodes("result", root);
Node server = getNodes("server", resultNode.getChildNodes());
Node checks = getNodes("checks", server.getChildNodes());
NodeList childNodes = checks.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node possibleCheck = childNodes.item(i);
if (possibleCheck.getNodeName().equals("check")) {
String checkid = getNodeValue("checkid", possibleCheck.getChildNodes());
System.out.println(checkid);
}
}
This way you'll be iterating through the correct node list.
Using XPath is more efficient and flexible (than normal iteration) while parsing xml.
XPath Tutorial from IBM
XPath Reference Orielly tutorial
Xpath Reference Oracle java tutorial
Try below code.
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class RequestResponse {
public static void main(String[] args) throws ParserConfigurationException,
IOException, SAXException {
URL url = new URL("http://belbooner.site40.net/testXmls/details.xml");
RequestResponse req = new RequestResponse();
req.getHTTPXml(url);
}
void getHTTPXml(URL url) throws ParserConfigurationException, IOException,
SAXException {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("ACCEPT", "application/xml");
InputStream xml = conn.getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document document = builder.parse(xml);
System.out.println(document);
String doctype = conn.getContentType();
System.out.println(doctype);
XPathFactory pathFactory = XPathFactory.newInstance();
XPath path = pathFactory.newXPath();
XPathExpression expression;
try {
expression = path.compile("/result/server/checks/check/checkid");
NodeList nodeList = (NodeList) expression.evaluate(document,
XPathConstants.NODESET);
String checkids[] = getNodeValue(nodeList);
for (String checkid : checkids) {
System.out.print(checkid + ", ");
}
} catch (XPathExpressionException e) {
e.printStackTrace();
}
conn.disconnect();
}
String[] getNodeValue(NodeList nodes) {
String checkIds[] = new String[nodes.getLength()];
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
checkIds[i] = node.getTextContent();
}
return checkIds;
}
}

Categories

Resources