DOM - Missing Element in XML Document - java

The XML file contains Employee (with empID, empName, empCode). In some situation empCode is missing.
<Employee><Detail><empID>1</empID><empName>Abhi</empName><empCode>One</empCode>
</Detail>
<Detail><empID>2</empID><empName>Amit</empName>
</Detail>
</Employee>
I am getting the Null pointer Exception while calling the getTagValue() method for "empCode" as there is no tag available with the name in XML.
Java Code :
try
{
File xmlFile = new File("New.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Detail");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE)
{
Element eElement = (Element) nNode;
EmpDetail empInfo = new EmpDetail();
empInfo.SetEmpID(getTagValue("empID", eElement));
empInfo.SetEmpName(getTagValue("empName",eElement));
empInfo.SetEmpCode(getTagValue("empCode",eElement));
DBConnector.SaveinDB(empInfo);
}
}
}
catch (Exception e)
{
System.out.println("Error: ");
e.printStackTrace();
}
}
private static String getTagValue(String sTag, Element eElement)
{
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
if(nValue == null)
return null;
return insertEscapeSequance(nValue.getNodeValue());
}
private static String insertEscapeSequance(String str)
{
String returnstr = "";
String[] strarr = str.split("'");
returnstr = strarr[0];
for(int i=1;i<strarr.length;i++)
{
returnstr = returnstr + "\\'" + strarr[i];
}
return returnstr;
}
Now I want to save the XML data into sql like this :
1 Abhi One
2 Amit null
I tried so many links but not success. Can someone please help me

If this is possible that there is no such value, then simply handle it like that:
if(getTagValue("empCode",eElement) != null){
empInfo.SetEmpCode(getTagValue("empCode",eElement));
}
Regarding to adding them into SQL, do the same check while creating your statement. As SQL NULL type exists

The problem is caused by eElement.getElementsByTagName(sTag).item(0). The statement returns the first node specified by sTag. In the case of empCode, null is returned, and calling getChildNodes() will raise a null pointer exception.
Try:
Node node = eElement.getElementsByTagName(sTag).item(0);
if (node != null) {
Node nValue = node.getChildNodes().item(0);
if (nValue != null) {
return insertEscapeSequance(nValue.getNodeValue());
}
}
return null;

Related

Java , XML User Verification Failure

I've been trying to make this work for longer than I'd like to say now and just can't figure out why it won't recognize the password,I get a null pointer exception on this line if (userPassword.getTextContent().equals(password)
Here is the method
public class XML {
public static boolean login(String email, String password) {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("data.xml");
Element root = document.getDocumentElement();
NodeList nList = root.getChildNodes();
for (int i = 0; i < nList.getLength(); i++) {
Node nNode = nList.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element users = (Element) nNode;
if (users.getNodeName().compareTo("users") == 0) {
NodeList userList = users.getChildNodes();
for (int j = 0; j < userList.getLength(); j++) {
Node userNode = userList.item(j);
NodeList AttributeList = userNode.getChildNodes();
Node userPassword = AttributeList.item(1);
Node userEmail = AttributeList.item(0);
if (userPassword.getTextContent().equals(password)
&& userEmail.getTextContent().equals(email)) {
return true;
}
}
}
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
}
return false;
}
Attribute nodes don't have text content but a value. You should use the following construct to retrieve it :
Node userNode = userList.item(j);
String attributeValue = userNode.getAttribute("attributeName")
Alternatively since you already have the attributes Nodes, you could cast them to org.w3c.dom.Attr and use their .getValue() method.

Getting attribute from XML document

I've looked on here for solutions, but I am still having problems getting this attribute from my xml document. I am trying to fetch the "1" from this: <update-comments total="1">
Here the code that I am using to fetch the other values without attributes:
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
doc = dbBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodes = doc.getElementsByTagName("update");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String update_type = getValue("update-type", element);
String numLikes = null;
String submittedUrl = null;
String comments = null;
if (update_type.equals("SHAR")) {
String shar_user = null;
String timestamp = null;
String id = null;
String updateKey = null;
String numComments = null;
try {
shar_user = getValue("first-name", element)
+ " " + getValue("last-name", element);
timestamp = getValue("timestamp", element);
id = getValue("id", element);
updateKey = getValue("update-key", element);
profilePictureUrl = getValue("picture-url", element);
numLikes = getValue("num-likes", element);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
private static String getValue(String tag, Element element)
{
NodeList nodes = element.getElementsByTagName(tag).item(0)
.getChildNodes();
Node node = (Node) nodes.item(0);
return node.getNodeValue();
}
This function will get an attribute value from an element using the same strategy that you used to find an element. (Note, you solution only works if an element actually exists.)
private static String getAttributeValue(String tag, Element element, String attribute)
{
NodeList nodes = element.getElementsByTagName(tag);
//note: you should actually check the list size before asking for item(0)
//because you asked for ElementsByTagName(), you can assume that the node is an Element
Element elem = (Element) nodes.item(0);
return elem.getAttribute(attribute);
}

Obtaining Xpath of all nodes in an xml

I have an xml. I want to obtain/print the Xpath(complete) of all the nodes in it using Java. I'm trying to use a DOM parser.
File stocks = new File("File Name");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(stocks);
System.out.println("Parsed successfully");
doc.getDocumentElement();
System.out.println("root of xml file : " + doc.getDocumentElement().getNodeName());
I'm able to get my root node to print, But not its children.
Strangely enough I just wrote a method that could be used for this. This however isn't fully namespace aware, so be warned, it also only works for ELEMENT types.
For this method to work you also need your document to be namespace aware. dbFactory.setNamespaceAware(true);. If you can't have it namespace aware then replace everywhere you see getLocalName() to getTagName().
try {
XPath xpath = XPathFactory.newInstance().newXPath();
// get all nodes in the document
NodeList nList = (NodeList) xpath.evaluate("//*", doc.getDocumentElement() ,XPathConstants.NODESET);
for(int i=0;i<nList.getLength();i++) {
if(nList.item(i).getNodeType() == Node.ELEMENT_NODE)
System.out.println(getElementXPath((Element)nList.item(i), doc.getDocumentElement()));
}
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/**
* Finds the xPath relative to the given node, the relativeTo should always be a parent of elt
* #param elt
* #param relativeTo should be a parent of elt, if it isnt the path from the document root will be returned
* #return
*/
public static String getElementXPath(Element elt, Element relativeTo) {
String path = "";
do {
String xname = elt.getLocalName() + "[" + getElementIndex(elt) + "]";
path = "/" + xname + path;
if(elt.getParentNode() != null && elt.getParentNode().getNodeType() == Element.ELEMENT_NODE)
elt = (Element) elt.getParentNode();
else
elt = null;
} while(elt != null && !elt.equals(relativeTo));
return path;
}
/**
* #param original
* #return the index this element is among its siblings, only accounts for siblings with the same tag name as itself. Used for xpath indexing
*/
private static int getElementIndex(Element original) {
int count = 1;
for (Node node = original.getPreviousSibling(); node != null; node = node.getPreviousSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.getLocalName().equals(original.getLocalName()) &&
(element.getNamespaceURI() == original.getNamespaceURI() || (element.getNamespaceURI() != null && element.getNamespaceURI().equals(original.getNamespaceURI())))) {
count++;
}
}
}
return count;
}

Java + reading data from XML file

What's wrong in this code? It gives me null everytime. I have no idea how to repair it, because in ordinary Java Application it works.
#WebMethod(operationName = "getColor")
public String getColor(#WebParam(name = "regNr") String regNr) {
String kolor=null;
try {
File fXmlFile = new File("/base.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("person");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) nNode;
String id = ""+ getValue("id",element);
if (regNr.equals(id)) {
color = element.getElementsByTagName("color").item(0).getTextContent();
return color;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return color;
}
I think (not sure because I don't know at which point it gives you null) you have to remove the / form the file name to become only base.xml

Java save / read data from XML - parsing exceptions

My little chat client software uses a XML file to store chat history, my class for handling reading / writing is:
public class History {
public String filePath;
public History(String filePath) {
this.filePath = filePath;
}
public String stripNonValidXMLCharacters(String in ) {
StringBuffer out = new StringBuffer(); // Used to hold the output.
char current; // Used to reference the current character.
if ( in == null || ("".equals( in ))) return ""; // vacancy test.
for (int i = 0; i < in .length(); i++) {
current = in .charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
if ((current == 0x9) ||
(current == 0xA) ||
(current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF)))
out.append(current);
}
return out.toString();
}
public synchronized void addMessage(String from, String agentName, String msg, String time, String channel) {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
org.w3c.dom.Document doc = docBuilder.parse(filePath);
Node data = doc.getFirstChild();
org.w3c.dom.Element root = doc.createElement(channel);
org.w3c.dom.Element message = doc.createElement("message");
org.w3c.dom.Element _sender = doc.createElement("sender");
_sender.setTextContent(stripNonValidXMLCharacters(from));
org.w3c.dom.Element _content = doc.createElement("content");
_content.setTextContent(stripNonValidXMLCharacters(msg));
org.w3c.dom.Element _recipient = doc.createElement("recipient");
_recipient.setTextContent(stripNonValidXMLCharacters(agentName));
org.w3c.dom.Element _time = doc.createElement("time");
_time.setTextContent(stripNonValidXMLCharacters(time));
message.appendChild(_sender);
message.appendChild(_content);
message.appendChild(_recipient);
message.appendChild(_time);
root.appendChild(message);
data.appendChild(root);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filePath));
transformer.transform(source, result);
} catch (Exception ex) {
System.out.println(ex.getStackTrace());
// This is being trown randomly
}
}
public synchronized void getHistory(String channel) {
try {
File fXmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
org.w3c.dom.Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName(channel);
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element eElement = (org.w3c.dom.Element) nNode;
if (getTagValue("sender", eElement).contains("Serv1")) {
printServerMsg(getTagValue("content", eElement).replace("%27", "'"), "", getTagValue("time", eElement));
} else {
printMsg(getTagValue("content", eElement).replace("%27", "'"), getTagValue("sender", eElement), getTagValue("time", eElement));
}
}
}
} catch (Exception ex) {
System.out.println("Filling Exception");
// This is also being trown
}
}
public String getTagValue(String sTag, org.w3c.dom.Element eElement) {
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
}
Exception when writing i am getting is:
`INVALID_CHARACTER_ERR: An invalid or illegal XML character is specified.``
And when reading the exception Filling exception
The exception here is java.lang.NullPointerException
Any ideas how i can guarantee that this wont happend? Problem is this basically breaks the whole client currently
Instead of
System.out.println("Filling Exception");
ALWAYS use either
e.printStackTrace();
Or a proper logging framework, like log4j, and log the error properly:
log.error("Filling Exception", e);
Why is this important?
Because by doing this, you could have provided the full stack trace for us...
Also, for escaping Strings to be used as XML content, it is wise to use an already well written, proven utility like the Apache commons StringEscapeUtils instead of reinventing the wheel
EDIT
From OPs comment
Oh thanks, i can now see that the error is in getTagValue()
There are multiple possibilities for NPE here, but the cuplrit is in this line
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
the following can be null
eElement.getElementsByTagName(sTag).item(0)
if there is no tag by that name in the document.
From the documentation:
Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
So I'd rewrite the method like this:
public String getTagValue(String sTag, org.w3c.dom.Element eElement) {
Node n = eElement.getElementsByTagName(sTag).item(0);
if(e !=null) {
NodeList nlList = n.getChildNodes();
Node nValue = (Node) nlList.item(0);
if(nValue != null) {
return nValue.getNodeValue();
}
}
return ""; // or return null; if that is more applicable to the use case
}
Also be careful that now this returns an empty string, which might or might not be good: it can go unnoticed that said node does not exist...

Categories