I'm going through a tutorial on how to parse an xml document with java and encountering a problem. I am getting the error "dom cannot be resolved" I know it has something to do with the way I am declaring the variables and being out of scope but I can't figure out how to fix it.
Any help would be greatly appreciated, I will post the relevant parts below:
package com.xmlparse;
import java.io.IOException;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import com.entities.Employee;
public class XmlParser
{
private void parseXmlFile(){
//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("test.xml");
} catch(ParserConfigurationException pce) {
pce.printStackTrace();
} catch(SAXException se) {
se.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
private void parseDocument() {
Document dom = db.parse("test.xml");
//get the root element
Element docEle = dom.getDocumentElement();
//get a nodelist of elements
NodeList nl = docEle.getElementsByTagName("Employee");
if(nl != null && nl.getLength() > 0) {
for(int i = 0 ; i < nl.getLength(); i++) {
//get the employee element
Element el = (Element)nl.item(i);
//get the Employee object
Employee e = getEmployee(el);
//add it to list
myEmpls.add(e);
}
}
}
As you are using DocumentBuilder db in different methods, you could declare db as a class member variable:
private DocumentBuilder db;
and initialize like so in parseXmlFile:
db = dbf.newDocumentBuilder();
You could change method signature like below and when call to it pass the created document builder instance.
private void parseDocument(DocumentBuilder db)
Related
I have to parse a String containing XML tags like the one hard coded below so that I can get values of all the tags separately. Here when I am using
NodeList node = doc.getElementsByTagName("event");
It is returning value as "ajain1AnkitJain24-04-199223:09.08"
I want to retrieve value for each tag and store it separately in different variables.
Like for eg in this scenario I want to Store Value as :
String UID = ajain1
String FirstName = Ankit
String LastName = Jain
Date date = "24-04-1992 23:09.08"
Here is the Sample code I am working on.
package test;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class Demo {
public static void main(String[] args) {
String xmldata = "<event><class></class><data><UID><![CDATA[ajain1]]></UID><FIRSTNAME><![CDATA[Ankit]]></FIRSTNAME><LASTNAME><![CDATA[Jain]]></LASTNAME><DATE><![CDATA[24-04-1992]]></DATE><TIME><![CDATA[23:09.08]]></TIME></data></event>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
try {
db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmldata));
try {
Document doc = db.parse(is);
//String message = doc.getDocumentElement().getTextContent();
//System.out.println(message);
NodeList node = doc.getElementsByTagName("event");
} catch (SAXException e) {
// handle SAXException
} catch (IOException e) {
// handle IOException
}
} catch (ParserConfigurationException e1) {
// handle ParserConfigurationException
}
// TODO Auto-generated method stub
}
}
Thanks and let me know if you require any more information.
A NodeList already is a list containing all requested nodes, but I have to admit, I find its implementation highly questionable. It's basically a node containing the requested nodes as children. Its implementation has very much nothing in common with other list implementations - it doesn't even implement the List interface. I don't exactly know how to handle [!CDATA], but to loop through all event tags you'd have to do something like this:
NodeList eventList = doc.getElementsByTagName("event");
for(int i = 0; i < eventList.getLength(); i++) {
Element eventElement = (Element) eventList.item(i);
// do some stuff with it
}
From this element, you can also use getElementsByTagName to get the information needed about first name and so on. And yes, it's likely to end up with many nested loops...
i need to split my xml into multiple xml based on the tag start and close. For this i tried with the following code
public class XmlSplit {
public static void main(String [] args) throws Exception {
File input = new File("/home/dev702/Desktop/cadgraf-test/Data_Entry.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = (Document) dbf.newDocumentBuilder().parse(input);
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate("//Data_x0020_Entry", doc, XPathConstants.NODESET);
int itemsPerFile = 500;
int fileNumber = 0;
Document currentDoc = (Document) dbf.newDocumentBuilder().newDocument();
Node rootNode;
rootNode = currentDoc.createElement("Data_x0020_Entry");
File currentFile = new File(fileNumber+".xml");
for (int i=1; i <= nodes.getLength(); i++) {
Node imported = currentDoc.importNode(nodes.item(i-1), true);
rootNode.appendChild(imported);
if (i % itemsPerFile == 0) {
writeToFile(rootNode, currentFile);
rootNode = currentDoc.createElement("Data_x0020_Entry");
currentFile = new File((++fileNumber)+".xml");
}
}
writeToFile(rootNode, currentFile);
}
private static void writeToFile(Node node, File file) throws Exception {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(node), new StreamResult(new FileWriter(file)));
}
}
In this am getting error on currentDoc.createElement. Am not able to compile this code and it is saying createElement not available.
Sample xml file
<?xml version="1.0" encoding="UTF-8"?>
<dataroot
xmlns:od="urn:schemas-microsoft-com:officedata"
xmlns:xsi="w3.org/2001/XMLSchema-instance" ;
xsi:noNamespaceSchemaLocation="Data%20Entry.xsd"
generated="2014-02-12T14:35:47"
>
<Data_x0020_Entry>
<ID>1004</ID>
<User>006Parthiban</User>
<Data_x0020_Entry_x0020_Date>2013-12-26T00:00:00</Data_x0020_Entry_x0020_Date>
<Publication>Daily Thanthi</Publication>
<Edition>CE City Edition</Edition>
<Location>Bangalore</Location>
</Data_x0020_Entry>
</dataroot>
I could not see any compilation issue in this code. Please check your import statements and verify that you have imported proper classes. the list of classes which I import are as below
import java.io.File;
import java.io.FileWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
i think u have imported import javax.swing.text.Document; change that to import org.w3c.dom.Document;
And if ur using Swing too than use fully qualified that for to create Document
like
org.w3c.dom.Document currentDoc = (org.w3c.dom.Document) dbf.newDocumentBuilder().newDocument();
Update
I think the root element should be "dataroot" for splitted xmls. and you need to change your code to generate correct number of xml files (look at below code)..look at the code below..i tested for
int itemsPerFile = 2; ..it is working fine..
NOTE remove ";" from input xml file after namespcae
import java.io.File;
import java.io.FileWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XmlSplit {
public static void main(String [] args) throws Exception {
File input = new File("src/test.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = (Document) dbf.newDocumentBuilder().parse(input);
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate("//Data_x0020_Entry", doc, XPathConstants.NODESET);
int itemsPerFile = 2;
int fileNumber = 0;
Document currentDoc = (Document) dbf.newDocumentBuilder().newDocument();
Node rootNode;
rootNode = currentDoc.createElement("dataroot");
File currentFile = new File(fileNumber+".xml");
for (int i=1; i <= nodes.getLength(); i++) {
Node imported = currentDoc.importNode(nodes.item(i-1), true);
rootNode.appendChild(imported);
if (i % itemsPerFile == 0) {
writeToFile(rootNode, currentFile);
rootNode = currentDoc.createElement("dataroot");
currentFile = new File((++fileNumber)+".xml");
}
else
{
writeToFile(rootNode, currentFile);
}
}
}
private static void writeToFile(Node node, File file) throws Exception {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(node), new StreamResult(new FileWriter(file)));
}
}
let me know if u face any issues :)
I'm trying to make a function that will take url and xpath as arguments, and query the xml file from supplied url and return String results. Here's my code: `package
uforia.tests.daoTests;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
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.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class XpathHelper {
public static final String NL = System.getProperty("line.separator");
#Test
public void testBelow() {
System.out.println(xmlQuery("http://abcnews.go.com/US/wireStory/10-things-today-19933443", "//*[#id=\"storyText\"]/p[3]"));
Assert.assertTrue(true);
}
public String xmlQuery(String url, String xpath) {
StringBuilder sb = new StringBuilder();
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); // Getting
// the
// instance
// of
// DocumentBuilderFactory
domFactory.setNamespaceAware(true); // true if the parser produced will
// provide support for XML
// namespaces;
try {
DocumentBuilder builder = domFactory.newDocumentBuilder();
// Creating document builder
Document doc = builder.parse(new URL(url).openStream()); // e.g.
XPath xPath = XPathFactory.newInstance().newXPath();
// getting instance of xPath
XPathExpression expr = xPath.compile(xpath);
// e.g. "//#id"
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
sb.append(nodes.item(i).getNodeValue()).append(NL);
}
}
catch (Exception e) {
e.printStackTrace();
}
// Think of closing connection in finnaly branch...
return sb.toString();
}
}
`
And I'm getting this error:
[Fatal Error] :37:108: The reference to entity "asset" must end with
the ';' delimiter. org.xml.sax.SAXParseException; lineNumber: 37;
columnNumber: 108; The reference to entity "asset" must end with the
';' delimiter.
I think the problem is with escaping ampersands, but I can't get it to work.
Thank for help in advance...
Following code is written to fetch the data from the xml file. I think it does fetch but in the object form. Why is that ?
package newpackage;
import java.io.File;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.util.LinkedList;
public class xmlParser {
private DocumentBuilder db;
private DocumentBuilderFactory dbf;
private Document dom;
private LinkedList list = new LinkedList();
public static void main(String args[]) {
xmlParser o = new xmlParser();
o.parseXML();
o.parseDocument();
o.print();
}
public void parseXML() { // getting a document builder
try {
dbf = DocumentBuilderFactory.newInstance();
db = dbf.newDocumentBuilder();
dom = db.parse(new File("Details.xml"));
} catch(Exception exc) {
exc.printStackTrace();
}
}
public void parseDocument() { // get a list of student elements
Element docEle = dom.getDocumentElement();
NodeList nl = docEle.getElementsByTagName("Details");
if(nl != null && nl.getLength() > 0) {
for(int i=0;i<nl.getLength();i++) {
Element el = (Element)nl.item(i);
Details details = new Details();
details = details.getDetail(el);
list.add(details);
}
}
}
public void print() {
// list.iterator();
// while(!list.isEmpty()) {
// System.out.println(list.pop().toString());
// }
Iterator it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next().toString());
}
}
}
Output :
newpackage.Details#1ac3c08
newpackage.Details#9971ad
newpackage.Details#1f630dc
newpackage.Details#1c5c1
Why do i get the output in the object form even after applying toString ?
When you want readable output, you have to override the toString() method in your newpackage.Details class ;)
Why do i get the output in the object form even after applying toString ?
Because you didn't override toString() method for that Details class
I'm having a little trouble parsing a string of xml called responseText in android. The xml is fully valid and has the following structure:
<plan>
<entry>
<name>john</name>
<address>uk</address>
</entry>
<entry>
<name>joe</name>
<address>usa</address>
</entry>
</plan>
The code I am using to parse the String is as follows:
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(responseText));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("entry");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList name = ((Document) element)
.getElementsByTagName("name");
Element line = (Element) name.item(0);
Toast.makeText(Containers.this,
getCharacterDataFromElement(line), Toast.LENGTH_SHORT)
.show();
NodeList title = ((Document) element)
.getElementsByTagName("address");
line = (Element) title.item(0);
Toast.makeText(Containers.this,
getCharacterDataFromElement(line), Toast.LENGTH_SHORT)
.show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getCharacterDataFromElement(Element e) {
Node child = ((Node) e).getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
I'm just using simple toasts to print the xml data to screen. However, i get an IOexception when I enter the for loop. Any idea what is wrong?
Are you importing the types from the correct packages? Something like
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import android.sax.Element; // Wrong Element class
Change the last import to
import org.w3c.dom.Element;
and try again.
I don't see anything that could cause an IOException inside the loop.
However, are you sure you can just go and cast an Element into a Document? At any rate you shouldn't need to anyways, since Element also has the getElementsByTagName method.
Try adding an xml declaration at the start of your string.