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
Related
I have created an XML parser to retrieve the information from an XML file to java, and then I am trying to store these data into an ArrayList in order to use the ArrayList for my methods.
It seems to work fine when I print it. However, I got a method called getAllRoutes for some reason it returns the wrong number of routes
Please move
routes.add(r);
inside
if (c.getNodeName().equals("Route")) {
Let me know if this helps Khaled.
Try this:
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 javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.List;
import java.util.ArrayList;
class Main {
public static Iterable<Node> iterable(final NodeList nodeList) {
return () -> new Iterator<Node>() {
private int index = 0;
#Override
public boolean hasNext() {
return index < nodeList.getLength();
}
#Override
public Node next() {
if (!hasNext())
throw new NoSuchElementException();
return nodeList.item(index++);
}
};
}
private static List<String> evaluateXPath(Document document, String xpathExpression)
{
// Create XPathFactory object
XPathFactory xpathFactory = XPathFactory.newInstance();
// Create XPath object
XPath xpath = xpathFactory.newXPath();
List<String> values = new ArrayList<>();
try
{
// Create XPathExpression object
XPathExpression expr = xpath.compile(xpathExpression);
// Evaluate expression result on XML document
NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
values.add(nodes.item(i).getNodeValue());
}
} catch (XPathExpressionException e) {
e.printStackTrace();
}
return values;
}
public static void main(String[] args) throws Exception {
//Build DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("data.xml");
//Create XPath
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
String xpathRoot = "//Routes/Route";
XPathExpression expr = xpath.compile(xpathRoot);
int i = 0;
for (Node n : iterable((NodeList) expr.evaluate(doc, XPathConstants.NODESET))) {
i++;
String xpe2 = String.format("%s[%d]/%s/text()", xpathRoot, i, "FlightNumber");
System.out.println("FxPe: " + xpe2);
System.out.println("Flight Number: " + evaluateXPath(doc, xpe2).get(0));
for (Node n2 : iterable(n.getChildNodes())) {
System.out.println(n2.getTextContent());
}
}
}
}
See it in action here
Useful links:
1: Iterate through NodeList
2: XPath CheatSheet
3: Java XPath Example a and b
4: NodeList Java docs
5: Node Java docs
And I would say. I your code:
Route r = new Route(); should be inside if statement
if (c.getNodeName().equals("Route"))
The commented out add is in the right place - the other place is wrong.
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...
This is the JAVA XML i'm parsing..
<objects>
<object>...<class>A /<class>...</object>
<object>...<class>B</class>....</object>
<object>...<class>A /<class>...</object>
</objects>
Now i split the XML into 3 XML's based on object tag with the below code.
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse("xml");
doc.getDocumentElement().normalize();
TransformerFactory tranFactory = TransformerFactory.newInstance();
Transformer aTransformer = tranFactory.newTransformer();
NodeList list =(NodeList) doc.getElementsByTagName("object");
System.out.println("XML SPLITED");
for (int i=0; i<list.getLength(); i++){
Node element = list.item(i).cloneNode(true);
if(element.hasChildNodes()){
Source src = new DOMSource(element);
FileOutputStream fs=new FileOutputStream("XML" + i + ".xml");
Result dest = new StreamResult(fs);
aTransformer.transform(src, dest);
fs.close();
}
My requirement is to get only the files with class tag A.So my output will be only 2 XML's.Please post your answers.
Using your example, you can do that this way:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
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.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XmlSplitting {
private static final Logger logger = Logger.getLogger(XmlSplitting.class.getName());
private static final String FILE_PATH = "./";
private DocumentBuilder builder;
private Transformer transformer;
public XmlSplitting() throws ParserConfigurationException, TransformerConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
this.builder = factory.newDocumentBuilder();
TransformerFactory transfromerFactory = TransformerFactory.newInstance();
this.transformer = transfromerFactory.newTransformer();
}
public static void main(String[] args) {
try {
XmlSplitting s = new XmlSplitting();
s.run();
} catch (ParserConfigurationException | SAXException | IOException | TransformerException x) {
logger.log(Level.SEVERE, "Error", x);
}
}
private void run() throws ParserConfigurationException, SAXException, IOException, TransformerException {
File file = new File(FILE_PATH + "xml.xml");
if (file.exists()) {
Document document = this.builder.parse(file);
document.normalize();
NodeList list = document.getElementsByTagName("object");
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
if (Node.ELEMENT_NODE == node.getNodeType()) {
Element object = (Element)node;
NodeList classes = object.getElementsByTagName("class");
if (1 == classes.getLength()) {
Node clazz = classes.item(0);
if (Node.ELEMENT_NODE == clazz.getNodeType()) {
this.copyNodeToNewFile(clazz.getTextContent(), node, i);
}
} else {
logger.log(Level.SEVERE, "Number of class nodes in node object is different than expected. Number of class nodes found: {0}.", classes.getLength());
}
}
}
} else {
logger.log(Level.SEVERE, "You provided wrong path for xml file.");
}
}
private void copyNodeToNewFile(String content, Node node, int i) throws IOException, TransformerException {
boolean copy = this.nodeShouldBeCopied(content);
logger.log(Level.INFO, "Node with content {0} will {1}be moved to separete file.", new Object[]{content, true == copy ? "" : "not "});
if (copy) {
String fileName = String.format("%sxml%d.xml", FILE_PATH, i);
try (FileOutputStream fos = new FileOutputStream(fileName)) {
Source source = new DOMSource(node);
Result destination = new StreamResult(fos);
this.transformer.transform(source, destination);
}
}
}
// here you can change condition to copy given node to file
private boolean nodeShouldBeCopied(String content) {
return content.contains("A");
}
}
How about using a Brazilian framework to parse your XML? it will make your code more exotic and you can tell your friends about it:
http://jcoltrane.sourceforge.net/userguide/extending_parsing_process.html
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)
I have a problem in getting the value of an element by providing the XPath using java. I tried lot of things but could not succeed.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
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.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.dell.logistics.framework.transform.NamespaceContext;
public class GetXPath {
protected Object evaluate(String xpathStr, String xml, String namespaces) throws XPathExpressionException {
InputSource inputSource = new InputSource(new StringReader(xml));
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
NamespaceContext nsContext = new NamespaceContext();
nsContext.setNamespacesMap(getNsMap(namespaces));
//System.out.println(nsContext.getPrefix(namespaces));
xPath.setNamespaceContext(nsContext);
XPathExpression xpExp = xPath.compile(xpathStr);
return xpExp.evaluate(inputSource, XPathConstants.NODESET);
}
private Map<String, String> getNsMap(String namespaces) {
String delims = ",";
String[] nsKeyValue = namespaces.split(delims);
Map<String, String> mp = new HashMap<String, String>();
for (String string : nsKeyValue) {
mp.put(string.split("=")[0], string.split("=")[1]);
System.out.println(string.split("=")[0] + string.split("=")[1]);
}
return mp;
}
public static String readFile(String fileName) {
try {
// InputStream is = null;
InputStream is = GetWorkOrderDataExtractor.class.getResourceAsStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String l = null;
while ((l = br.readLine()) != null) {
sb.append(l).append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException {
GetXPath g = new GetXPath();
String xml = readFile("fooewo.xml");
String value = null;
System.out.println(xml);
NodeList containerNodes = (NodeList) g.evaluate(
"/demo",xml,
"a=http://schemas.demo.com/it/WorkOrderChannelAckNackResponse/1.0");
try{
for (int i = 0; i < containerNodes.getLength(); i++) {
// get the node value.
value = containerNodes.item(i).getTextContent();
System.out.println(value);
}
System.out.println("Node Found : " + containerNodes.getLength() + " times");
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
"
XML file:
<?xml version="1.0" encoding="utf-8"?>
<demo xmlns="try with ur schema">
<test>
<value>10</value>
<color>red</color>
<animal>dog</animal>
<day>13</day>
<age>22</age>
</test>
<test>
<value>20</value>
<color>green</color>
<animal>cat</animal>
<day>12</day>
<age>23</age>
</test>
</demo>
Any help appreciated.
Thanks,
Pradeep
I think the best way to evaluate XPath easily is using AXIOMXPath
Here is an example,
OMElement documentElement = new StAXOMBuilder(inStreamToXML).getDocumentElement();
AXIOMXPath xpathExpression = new AXIOMXPath ("/demo");
List nodeList = (OMNode)xpathExpression.selectNodes(documentElement);
By traversing the list you can get the result easily.