XML parsing with Child not value parsing
import java.io.File;
import java.io.FileInputStream;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import com.sun.org.apache.xml.internal.dtm.ref.DTMNodeList;
public class XPathEvaluator {
/*
* ServiceGroup serviceGroup = new ServiceGroup(); List<Service>
* requiredServices = new ArrayList<Service>(); List<Service>
* recommandedServices = new ArrayList<Service>(); Service service = new
* Service();
*/
public void evaluateDocument(File xmlDocument) {
try {
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
String requiredServicesExpression = "/Envelope/Header";
InputSource requiredServicesInputSource = new InputSource(
new FileInputStream(xmlDocument));
DTMNodeList requiredServicesNodes = (DTMNodeList) xPath.evaluate(
requiredServicesExpression, requiredServicesInputSource,
XPathConstants.NODESET);
System.out.println(requiredServicesNodes.getLength());
NodeList requiredNodeList = (NodeList) requiredServicesNodes;
for (int i = 0; i < requiredNodeList.getLength(); i++) {
Node node = requiredNodeList.item(i);
System.out.println(node.getChildNodes());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] argv) {
XPathEvaluator evaluator = new XPathEvaluator();
File xmlDocument = new File("d://eva.xml");
evaluator.evaluateDocument(xmlDocument);
}
}
my xml is following in this i am try to parse header information
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Header>
<User id="MAKRISH"/>
<Request-Id id="1"/>
<Type name="Response"/>
<Application-Source name="vss" version="1.0"/>
<Application-Destination name="test" />
<Outgo-Timestamp date="2012-08-24" time="14:50:00"/>
<DealerCode>08301</DealerCode>
<Market>00000</Market>
</Header>
</Envelope>
i am not able to get Header child how can i get them it is giving me null on getchildNodes method. i have check for many solution but get any thing.
The following parsing is done with DOM as per tagging , i hope this should help you to solve
{
try{
File file = new File("xmlfile");
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(file);
Element root = document.getDocumentElement();
root.normalize();
printNode(root, 0);
} catch (Exception e) {
}
}
public static void printNode(Node node, int depth) {
if (node.getNodeType() == Node.TEXT_NODE) {
System.out.printf("%s%n", node.getNodeValue());
} else {
NamedNodeMap attributes = node.getAttributes();
if ((attributes == null) || (attributes.getLength() == 0)) {
System.out.printf("%s%n", node.getNodeName());
} else {
System.out.printf("%s ", node.getNodeName());
printAttributes(attributes);
}
}
NodeList children = node.getChildNodes();
for(int i=0; i<children.getLength(); i++) {
Node childNode = children.item(i);
printNode(childNode, depth+1);
}
}
private static void printAttributes(NamedNodeMap attributes) {
for(int i=0; i<attributes.getLength(); i++)
{
Node attribute = attributes.item(i);
System.out.printf(" %s=\"%s\"", attribute.getNodeName(),
attribute.getNodeValue());
}
}
}
The accepted answer to this related question has a good example of parsing xml using xpath.
I've debugged into your code, and the getChildNodes call is in fact not returning null, but it has got a confusing toString().
Related
This is an academic assignment and we are given an extremely large XML file with hundreds of entries like these. For each item we are supposed to list the Manager's ID, the Person's ID of the last person to add an item to the list, and the current number of items. I have read and reread the Oracle DOM API and various Node APIs. We are using JAVA and I cannot for the life of me figure out how to search various 'fields' of each item_list node. Below is an example of the data we are given.
<item_list id="item_list01">
<numitems_intial>5</numitems_initial>
<item>
<date_added>1/1/2014</date_added>
<added_by person="person01" />
</item>
<item>
<date_added>1/6/2014</date_added>
<added_by person="person05" />
</item>
<numitems_current>7</numitems_current>
<manager person="person48" />
</item_list>
<item_list id="item_list02">
<numitems_intial>5</numitems_initial>
<item>
<date_added>1/15/2014</date_added>
<added_by person="person05" />
</item>
<item>
<date_added>1/1/2014</date_added>
<added_by person="person09" />
</item>
<item>
<date_added>1/9/2014</date_added>
<added_by person="person45" />
</item>
<numitems_current>7</numitems_current>
<manager person="person38" />
</item_list>
I've tried doing something similar to:
NodeList nodes = queryDoc.getElementsByTagName("item_list");
for(int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if(node != null) {
System.out.println(node.manager);
}
}
And messing around with this code for a while, but I would like to know how to retrieve data from various fields in each node.
If you are trying to read person attribute of manager tag, you can do it as shown below -
import java.io.IOException;
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.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class Test{
public static void main (String[] args)
{
Test test = new Test();
test.readXML();
}
private void readXML()
{
Document doc = null;
try
{
doc = parseXML("/home/abc/Test.xml");
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
catch (SAXException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
if(doc != null)
{
NodeList nList = doc.getElementsByTagName("item_list");
for (int i = 0; i < nList.getLength(); i++)
{
Node nNode = nList.item(i);
Element eElement = (Element) nNode;
Element cElement = (Element) eElement.getElementsByTagName("manager").item(0);
System.out.println("Manager ID : " + cElement.getAttribute("person"));
}
}
}
private Document parseXML(String filePath) throws ParserConfigurationException, SAXException, IOException
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(filePath);
doc.getDocumentElement().normalize();
return doc;
}
}
Or, using xml you might need to edit the initial content. I suggest the following approach
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
public class ReadXML {
public static void main(String[] args) {
try {
Document doc = getDocument("/home/abc/Test.xml");
System.out.println(getString(getNodeByName(doc,"item_list01")));
} catch (TransformerException | ParserConfigurationException | IOException | SAXException e) {
// Log e.printStackTrace();
}
}
private static Document getDocument(String filePath) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
return docBuilder.parse(filePath);
}
private static String getString(Node node) throws TransformerException {
StringWriter sw = new StringWriter();
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
return sw.toString();
}
public static Node getNodeByName(Document doc, String nodeName) {
Node node = null;
for (int i = 0; i < doc.getDocumentElement().getChildNodes().getLength(); i++) {
if (!getTagName(doc, i).equals("#text")) {
for (int j = 0; j < getNodeName(doc, i).getChildNodes().getLength(); j++) {
if (getNodeName(doc, i, j).equalsIgnoreCase("item_list") && getNodeAttributes(doc,i,j).equalsIgnoreCase(nodeName)) {
node = getNodeName(doc, i);
}
}
}
}
return node;
}
private static String getTagName(Document doc, int i) {
return getNodeName(doc, i).getNodeName();
}
private static Node getNodeName(Document doc, int i) {
return (doc.getDocumentElement().getChildNodes().item(i));
}
private static String getNodeName(Document doc, int i, int j) {
return getNodeName(doc, i).getChildNodes().item(j).getNodeName();
}
private static String getNodeAttributes(Document doc, int i, int j) {
if(getNodeName(doc, i).getChildNodes().item(j).hasAttributes()){
return getNodeName(doc, i).getChildNodes().item(j).getAttributes().item(0).getNodeValue();
}
return "";
}
}
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'm building a simple currency converter which needs to sue online rates. I found the following API from the European Central Bank to use:
http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
My problem is im struggling to implement it. Here is what i have so far after using a bunch of different sources to try and get this code together.
try{
URL url = new URL("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
NodeList nodeList1 = doc.getElementsByTagName("Cube");
for(int i = 0; i < nodeList1.getLength(); i++){
Node node = nodeList1.item(i);
}
}
catch(Exception e){
}
So what i thought is that this code would take down all the nodes which tart with "Cube", and contain the rates.
Anyone have an easier wya to pull down the rates from the API into an array in the order they appear on the XML as that's all I'm trying to do
Thanks
XPath is one way to answer this, since you just want to extract information from the XML and not change the XML. The structure of the XML suggests that you're looking for nodes that are Cube nodes, that are child of Cube which is also a child of Cube -- Cube nested three times, so extract nodes with an XPath compiled using this String: "//Cube/Cube/Cube". This looks for nodes that have Cube nested 3 times located anywhere (the //) in the Document:
XPathExpression expr = xpath.compile("//Cube/Cube/Cube");
Then check the nodes for a "currency" attribute. If they have this, then they also have a "rate" attribute, and then extract this information.
NamedNodeMap attribs = node.getAttributes();
if (attribs.getLength() > 0) {
Node currencyAttrib = attribs.getNamedItem(CURRENCY);
if (currencyAttrib != null) {
String currencyTxt = currencyAttrib.getNodeValue();
String rateTxt = attribs.getNamedItem(RATE).getNodeValue();
// ...
}
}
Where CURRENCY = "currency" and RATE = "rate"
For example:
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class TestXPath {
private static final String CURRENCY = "currency";
private static final String CUBE_NODE = "//Cube/Cube/Cube";
private static final String RATE = "rate";
public static void main(String[] args) {
List<CurrencyRate> currRateList = new ArrayList<>();
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document document = null;
String spec = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
try {
URL url = new URL(spec);
InputStream is = url.openStream();
document = builder.parse(is);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
String xPathString = CUBE_NODE;
XPathExpression expr = xpath.compile(xPathString);
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
NamedNodeMap attribs = node.getAttributes();
if (attribs.getLength() > 0) {
Node currencyAttrib = attribs.getNamedItem(CURRENCY);
if (currencyAttrib != null) {
String currencyTxt = currencyAttrib.getNodeValue();
String rateTxt = attribs.getNamedItem(RATE).getNodeValue();
currRateList.add(new CurrencyRate(currencyTxt, rateTxt));
}
}
}
} catch (SAXException | IOException | XPathExpressionException e) {
e.printStackTrace();
}
for (CurrencyRate currencyRate : currRateList) {
System.out.println(currencyRate);
}
}
}
public class CurrencyRate {
private String currency;
private String rate; // ?double
public CurrencyRate(String currency, String rate) {
super();
this.currency = currency;
this.rate = rate;
}
public String getCurrency() {
return currency;
}
public String getRate() {
return rate;
}
#Override
public String toString() {
return "CurrencyRate [currency=" + currency + ", rate=" + rate + "]";
}
// equals, hashCode,....
}
I have an XML String. I'm trying to convert that string into map so that I can get key & value. However its not able to convert. Here is my code
String xmlString = "<?xml version="1.0" encoding="UTF-8"?><user>
<kyc></kyc>
<address></address>
<resiFI></resiFI></user>"
def convertStringToDocument = {
xmlString ->
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
def populateDocProofsFromWaiversXML = {
xmlString, mandateFlag ->
final List<DocumentProof> documentProofs = new ArrayList<DocumentProof>();
if (xmlString != null) {
try {
HashMap<String, String> values = new HashMap<String, String>();
Document xml = convertStringToDocument(waiversList);
org.w3c.dom.Node user = xml.getFirstChild();
NodeList childs = user.getChildNodes();
org.w3c.dom.Node child;
for (int i = 0; i < childs.getLength(); i++) {
child = childs.item(i);
System.out.println(child.getNodeName());
System.out.println(child.getNodeValue());
values.put(child.getNodeName(), child.getNodeValue());
}
} catch (Throwable t) {
println "error"
//LOG.error("Could not set document proofs from waivers ", t);
}
}
return documentProofs;
}
I'd like to get "kyc" as key and the respective value. Any better ideas?
package com.test;
import java.io.StringReader;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class Random {
/**
* #param args
*/
public static void main(String[] args) {
HashMap<String, String> values = new HashMap<String, String>();
String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><user><kyc>123</kyc><address>test</address><resiFI>asds</resiFI></user>";
Document xml = convertStringToDocument(xmlString);
Node user = xml.getFirstChild();
NodeList childs = user.getChildNodes();
Node child;
for (int i = 0; i < childs.getLength(); i++) {
child = childs.item(i);
System.out.println(child.getNodeName());
System.out.println(child.getTextContent());
values.put(child.getNodeName(), child.getTextContent());
}
}
private static Document convertStringToDocument(String xmlStr) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(
xmlStr)));
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
This will work. Please check :)
You can play with DOM.
I need help in the below concept.
I want to get attributes of xref node in the code. i.e id and its value, location and its value, type and its value.
I am passing xml as string. But the document shows null on parsing.
PLease help me in this.
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.NodeList;
import org.xml.sax.InputSource;
public class GetAtrribute {
/**
* #param args
*/
public static void main(String[] args) {
String xml = "<xref id=\"19703675\" location=\"abstract\" type=\"external\">PubMed Abstract: http://www.abcd.nlm.nih.gov/...</xref>"; //Populated XML String....
GetAtrribute ga = new GetAtrribute();
try {
ga.getValues(xml);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getValues(String xmlStr) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + xmlStr;
try {
builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(
xmlStr)));
Element element = document.getDocumentElement();
NodeList list = element.getElementsByTagName("xref");
if (list != null && list.getLength() > 0) {
NodeList subList = list.item(0).getChildNodes();
if (subList != null && subList.getLength() > 0) {
return subList.item(0).getNodeValue();
}
for (int count = 0; count < subList.getLength(); count++) {
System.out.println(subList.item(count).getNodeValue());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return xmlStr;
}
}
Your problem is that when you run this line:
Element element = document.getDocumentElement();
you're actually selecting xref already, because its the only xml element. You could either wrap another object around xref, or just use the variable 'element' to get the details.
p.s. your class name is spelt wrong: GetAtrribute -> GetAttribute
I suggest you to use XPath to find data in your XML:
XPath xPath = XPathFactory.newInstance().newXPath();
Document baseDoc;
try (InputStream pStm = new ByteArrayInputStream(baseXmlString.getBytes("utf-8"))) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
baseDoc = builder.parse(pStm);
} catch (SAXException | IOException | ParserConfigurationException ex) {
getLogger().error(null, ex);
return null;
}
try {
XPathExpression expression = xPath.compile(xPathExpression);
return (T) expression.evaluate(baseDoc, pathType);
} catch (XPathExpressionException ex) {
getLogger().error(null, ex);
}
return null;
For example take a look at here