So I am having a lot of trouble reading this XML file:
<?xml version = "1.0" encoding = "UTF-8"?>
<!--this version of Eclipse dosn't support direct creation of XML files-->
<!-- you have to create one in notepad and then copy/paste it into Eclipse-->
<root testAttribute = "testValue">
<data>Phoebe</data>
<data>is</data>
<data>a</data>
<data>puppy!</data>
<secondElement testAttribute = "testValueAgain">
<data2>Poop</data2>
<data2>Doopy</data2>
</secondElement>
</root>
In my java file I get a NullPointerException in this one line.
Here's the code: (I'll point out where the exception occurs)
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;
import java.io.*;
public class Reading {
public static void main(String args[]){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("res/Test.xml"));
////////////////////GET ELEMENTS//////////////////
Element rootElement = doc.getDocumentElement();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
System.out.println("testAttribute for root element: "
+ rootElement.getAttribute("testAttribute"));
Element secondElement = doc.getElementById("secondElement");
System.out.println("testAttribute for second element: " +
secondElement.getAttribute("testAttribute")); //THIS IS THE LINE
NodeList list = rootElement.getElementsByTagName("data");
NodeList list2 = rootElement.getElementsByTagName("data2");
//////////////////////////////////
for(int i = 0; i < list.getLength(); i++){
Node dataNode = list.item(i);
System.out.println("list index: " + i + " data at that index: " +
dataNode.getTextContent());
}
for(int i = 0; i < list2.getLength(); i++){
Node dataNode = list2.item(i);
System.out.println("list2 index: " + i + " data at that index: " +
dataNode.getTextContent());
}
}catch(ParserConfigurationException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(SAXException e){
e.printStackTrace();
}
}
}
Can you guys check out my code and tell me what I can do to avoid the NullPointerException? I'm really frustrated right now. Thanks!
P.S. some of you guys answered about the line above the line that got the exception. The exception occurs when I try to PRINT OUT the testAttribute value in the secondaryElement element.
getElementByID is not what you think it is, thus returns null (there are no id="..." attributes).
The quick answer is that your secondElement is null. The reason is because you have no element with id="secondElement". Your code expects the document to contain something like
<myelement id="secondElement">...</myelement>
Related
I am attempting to get the text from an xml node. The code seems to recognize the node. This code
String L = "Node Length: " + nList.getLength()+ " Text: " + nList.item(0).toString();
jTextArea1.setText(L);
returns: Node Length: 1 Text: [CompanyName: null]
So it seems like the code is finding the node but not getting the value. Here is the whole code block (this is my first time posting so I hope I formatted this right!). the FOR loop should grab the value but is throwing a NULL Pointer Exception:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try{
//Get Document Builder
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//Build Document
Document xdocument = builder.parse(new File("request.xml"));
xdocument.getDocumentElement().normalize();
NodeList nList = xdocument.getElementsByTagName("CompanyName");
//String L = "Node Length: " + nList.getLength()+ " Text: " + nList.item(0).toString();
//jTextArea1.setText(L);
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node node = nList.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
Element eElement = (Element) node;
String nodetxt= "Company : " + eElement.getElementsByTagName("CompanyName").item(0).getTextContent() ;
jTextArea1.setText(nodetxt) ;
}
}
} catch (Exception ex) {
java.util.logging.Logger.getLogger(TechKnowPOSGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
}
and here is the XML file:
<?xml version="1.0" encoding="utf-8"?>
<RunReportQueryAction xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CompanyName>Techknow</CompanyName>
<IntegrationLoginId>cwapitest</IntegrationLoginId>
<IntegrationPassword>cwtest123</IntegrationPassword>
<ReportName>Company</ReportName>
<!-- <Conditions></Conditions> -->
<!-- <Limit>10</Limit> -->
<!-- <Skip></Skip> -->
<!-- <OrderBy></OrderBy> -->
</RunReportQueryAction>
Any help is greatly appreciated.
On this line you get all the CompanyName elements:
NodeList nList = xdocument.getElementsByTagName("CompanyName");
Then you loop through them in your for loop and call this:
eElement.getElementsByTagName("CompanyName")
But that would imply that the CompanyName has nested CompanyName elements, which it does not. Therefore you should use this in your for loop, as the elements you are iterating are already the CompanyName elements:
String nodeTxt = "Company : " + eElement.getTextContent()
I am basically following the example here
http://www.mkyong.com/java/how-to-read-xml-file-in-java-jdom-example/
So rather than doing something like
node.getChildText("firstname")
right??
this works fine..
But is there a way to get all the "keys" and then I can query that to get values?
Just like we do in parsing json..
JSONObject json = (JSONObject) parser.parse(value);
for (Object key : json.keySet()) {
Object val = json.get(key);
}
rather than hardcoding keys and values?
Thanks
Code for reference:
package org.random_scripts;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
public class XMLReader {
public static void main(String[] args) {
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("data.xml");
try {
Document document = (Document) builder.build(xmlFile);
Element rootNode = document.getRootElement();
List list = rootNode.getChildren("staff");
List children = rootNode.getChildren();
System.out.println(children);
for (int i = 0; i < list.size(); i++) {
Element node = (Element) list.get(i);
System.out.println("First Name : " + node.getChildText("firstname"));
System.out.println("Last Name : " + node.getChildText("lastname"));
System.out.println("Nick Name : " + node.getChildText("nickname"));
System.out.println("Salary : " + node.getChildText("salary"));
}
} catch (IOException io) {
System.out.println(io.getMessage());
} catch (JDOMException jdomex) {
System.out.println(jdomex.getMessage());
}
}
}
Well, if you wanted to write out all of the children of the node, you could do something like this:
List children = rootNode.getChildren();
for (int i = 0; i < list.size(); i++) {
Element node = (Element) list.get(i);
List dataNodes = node.getChildren();
for (int j = 0; j < dataNodes.size(); ++j) {
Element dataNode = (Element) dataNodes.get(j);
System.out.println(dataNode.getName() + " : " + dataNode.getText());
}
}
This would let you write out all of the children without knowing the names, with the only downside being that you wouldn't have "pretty" names for the fields (i.e. "First Name" instead of "firstname"). Of course, you'd have the same limitation in JSON - I don't know of an easy way to get pretty names for the fields unless your program has some knowledge about what the children are, which is the thing you seem to be trying to avoid.
The above code only provides the list of 1st level child under the tag.
For example::
<parent>
<child1>
<childinternal></childinternal>
</child1>
<child2></child2>
</parent>
The above code only prints child1 and child2, if you want to print even the internal nodes in depth you have to do recursive call.
To find a child has more nodes in it use, jdom api child.getContentSize(), if its greater than 1 menas it has more nodes.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Traversing complex xml File in android
In this i am parsing an xml file using DOM parser which is giving me dom1 as the parsed document.
the problem is that i want to create UI after this,and i am unable to the same as i can't find a logic to the same please help me with that.Also this is giving me wrong getLength() values. What is wrong with it??
the xml is in this link:
http://nchc.dl.sourceforge.net/project/trialxml/options.xml
//this is function is called when i click my button
public void next123(View view){
Element root=dom1.getDocumentElement();
NodeList nodes=root.getChildNodes();
create_Menu(nodes);
}
public void create_Menu(NodeList nodes){
for(int i=0;i<nodes.getLength();i++){
Node node=nodes.item(i);
if(node instanceof Element){
Element child = (Element)node;
String name=getTextValue(child,"Name");
String typ=child.getAttribute("type");
if(name!=null){
z++;
Log.i(TAG,"Names are:= " +name+ " -> "+typ +" -> "+ z+ " -> "+ i);
NodeList nod=child.getChildNodes();
Log.i(TAG,"Length : "+nod.getLength());
create_Menu(nod);
Log.i(TAG,"end");
}
}
}
}
i have to create a UI after this, for that i am using ListView and an array of ArrayList to store my values. the problem is i have to assign a no. to every level,
for example if my array is test[], then
test[0]-> main,
test[1]->1L1,1L2,1L3,
test[2]->2L1,
test[3]->2L2
test[4]->3L1,3L2
please the xml for refrence.
I am just giving an example, try to do it this way....
DocumentBuilderFactory odbf = DocumentBuilderFactory.newInstance();
DocumentBuilder odb = odbf.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xml));
Document odoc = odb.parse(is);
odoc.getDocumentElement().normalize (); // normalize text representation
System.out.println ("Root element of the doc is " + odoc.getDocumentElement().getNodeName());
NodeList LOP = odoc.getElementsByTagName("locations");
int totalPersons =LOP.getLength();
System.out.println("Total nos of locations:"+totalPersons);
for(int s=0; s<LOP.getLength() ; s++)
{
Node FPN =LOP.item(s);
if(FPN.getNodeType() == Node.ELEMENT_NODE)
{
Element latlon = (Element)FPN;
NodeList oNameList1 = latlon.getElementsByTagName("featured");
Element firstNameElement = (Element)oNameList1.item(0);
NodeList textNList1 = firstNameElement.getChildNodes();
featuredArr = changeToBoolean(((Node)textNList1.item(0)).getNodeValue().trim()); // value taken
System.out.println("#####The Parsed data#####");
System.out.println("featured : " + ((Node)textNList1.item(0)).getNodeValue().trim());
System.out.println("#####The Parsed data#####");
}
}
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);
}
I can't fetch text value with Node.getNodeValue(), Node.getFirstChild().getNodeValue() or with Node.getTextContent().
My XML is like
<add job="351">
<tag>foobar</tag>
<tag>foobar2</tag>
</add>
And I'm trying to get tag value (non-text element fetching works fine). My Java code sounds like
Document doc = db.parse(new File(args[0]));
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();
Node an,an2;
for (int i=0; i < nl.getLength(); i++) {
an = nl.item(i);
if(an.getNodeType()==Node.ELEMENT_NODE) {
NodeList nl2 = an.getChildNodes();
for(int i2=0; i2<nl2.getLength(); i2++) {
an2 = nl2.item(i2);
// DEBUG PRINTS
System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");
if(an2.hasChildNodes())
System.out.println(an2.getFirstChild().getTextContent());
if(an2.hasChildNodes())
System.out.println(an2.getFirstChild().getNodeValue());
System.out.println(an2.getTextContent());
System.out.println(an2.getNodeValue());
}
}
}
It prints out
tag type (1):
tag1
tag1
tag1
null
#text type (3):
_blank line_
_blank line_
...
Thanks for the help.
I'd print out the result of an2.getNodeName() as well for debugging purposes. My guess is that your tree crawling code isn't crawling to the nodes that you think it is. That suspicion is enhanced by the lack of checking for node names in your code.
Other than that, the javadoc for Node defines "getNodeValue()" to return null for Nodes of type Element. Therefore, you really should be using getTextContent(). I'm not sure why that wouldn't give you the text that you want.
Perhaps iterate the children of your tag node and see what types are there?
Tried this code and it works for me:
String xml = "<add job=\"351\">\n" +
" <tag>foobar</tag>\n" +
" <tag>foobar2</tag>\n" +
"</add>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes());
Document doc = db.parse(bis);
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();
Node an,an2;
for (int i=0; i < nl.getLength(); i++) {
an = nl.item(i);
if(an.getNodeType()==Node.ELEMENT_NODE) {
NodeList nl2 = an.getChildNodes();
for(int i2=0; i2<nl2.getLength(); i2++) {
an2 = nl2.item(i2);
// DEBUG PRINTS
System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");
if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getTextContent());
if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getNodeValue());
System.out.println(an2.getTextContent());
System.out.println(an2.getNodeValue());
}
}
}
Output was:
#text: type (3): foobar foobar
#text: type (3): foobar2 foobar2
If your XML goes quite deep, you might want to consider using XPath, which comes with your JRE, so you can access the contents far more easily using:
String text = xp.evaluate("//add[#job='351']/tag[position()=1]/text()",
document.getDocumentElement());
Full example:
import static org.junit.Assert.assertEquals;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
public class XPathTest {
private Document document;
#Before
public void setup() throws Exception {
String xml = "<add job=\"351\"><tag>foobar</tag><tag>foobar2</tag></add>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
document = db.parse(new InputSource(new StringReader(xml)));
}
#Test
public void testXPath() throws Exception {
XPathFactory xpf = XPathFactory.newInstance();
XPath xp = xpf.newXPath();
String text = xp.evaluate("//add[#job='351']/tag[position()=1]/text()",
document.getDocumentElement());
assertEquals("foobar", text);
}
}
I use a very old java. Jdk 1.4.08 and I had the same issue. The Node class for me did not had the getTextContent() method. I had to use Node.getFirstChild().getNodeValue() instead of Node.getNodeValue() to get the value of the node. This fixed for me.
If you are open to vtd-xml, which excels at both performance and memory efficiency, below is the code to do what you are looking for...in both XPath and manual navigation... the overall code is much concise and easier to understand ...
import com.ximpleware.*;
public class queryText {
public static void main(String[] s) throws VTDException{
VTDGen vg = new VTDGen();
if (!vg.parseFile("input.xml", true))
return;
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
// first manually navigate
if(vn.toElement(VTDNav.FC,"tag")){
int i= vn.getText();
if (i!=-1){
System.out.println("text ===>"+vn.toString(i));
}
if (vn.toElement(VTDNav.NS,"tag")){
i=vn.getText();
System.out.println("text ===>"+vn.toString(i));
}
}
// second version use XPath
ap.selectXPath("/add/tag/text()");
int i=0;
while((i=ap.evalXPath())!= -1){
System.out.println("text node ====>"+vn.toString(i));
}
}
}