Regarding XPath using Java - java

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.

Related

Passing parameters to REST web-service

I'm dealing with the problem with passing parameteres to web-service.
I have created web-service which works OK for the case fromLanguage = "eng"
But, when I test service through Glassfish console and send fromLanguage = "bos" I don't get appropriate result.
package pckgTranslator;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
#Path("/MyRestService/{wordToTranslate},{fromLanguage},{toLanguage}")
public class clsTranslate {
#GET
public String doGet(#PathParam("wordToTranslate") String wordToTranslate,
#PathParam("fromLanguage") String fromLanguage, #PathParam("toLanguage") String toLanguage)
throws Exception{
Translator translator = new Translator();
return translator.getTranslation(wordToTranslate,fromLanguage, toLanguage);
}
}
This is XML fajl which I try to parse:
<?xml version="1.0" encoding="utf-8" ?>
<gloss>
<word id="001">
<eng>ball</eng>
<bos>lopta</bos>
</word>
<word id="002">
<eng>house</eng>
<bos>kuca</bos>
</word>
<word id="003">
<eng>game</eng>
<bos>igra</bos>
</word>
</gloss>
And this is the class which I'm using for parsing XML.
package pckgTranslator;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class Translator {
String translation = null;
String getTranslation(String wordForTransl, String fromLanguage, String toLanguage)
throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
//fromLanguage = "eng";
//toLanguage = "bos";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream is = Translator.class.getResourceAsStream("/resource/glossary.xml");
Document doc = builder.parse(new InputSource(is));
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
//XPathExpression expr = null; //xpath.compile("//word[eng='house']/bos/text()");
XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
if (fromLanguage == "eng") {
expr = xpath.compile("//word[eng='" + wordForTransl + "']/bos/text()");
} else if (fromLanguage == "bos") {
expr = xpath.compile("//word[bos='" + wordForTransl + "']/eng/text()");
}
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
//System.out.println(nodes.item(i).getNodeValue());
translation = nodes.item(i).getNodeValue();
}
//return nodes.item(i).getNodeValue();
if (translation != null) {
return translation;
} else {
return "We are sorry, there is no translation for this word!";
}
}
}
It seems to me that something is wrong with the parameters fromLanguage and toLanguage, but I can't realize what exactly.
Thanks in advance.
As I mentioned in the comment, you have hardcoded fromLanguage and toLanguage variables to eng and bos at the beginning of getTranslation() method. Due to this, the fromLanguage and 'toLangugaevalues passed togetTranslation()` method are lost.
Secondly, instead of separating #PathParm by , separate those by /. It will look like:
#Path("/MyRestService/{wordToTranslate}/{fromLanguage}/{toLanguage}")
#GET
public String doGet(#PathParam("wordToTranslate") String wordToTranslate,
#PathParam("fromLanguage") String fromLanguage, #PathParam("toLanguage") String toLanguage) throws Exception
Invocation: curl -X GET http://localhost:8080/MyRestService/x/y/z
Alternatively use #QueryParam. In that case your path would be:
#Path("/MyRestService")
public String doGet(#QueryParam("wordToTranslate") String wordToTranslate,
#QueryParam("fromLanguage") String fromLanguage, #QueryParam("toLanguage") String toLanguage) throws Exception
Invocation: curl -X GET http://localhost:8080/MyRestService?wordToTranslate=x&fromLanguage=y&toLanguage=z
Remove or comment the below lines in getTranslation() method:
fromLanguage = "eng";
toLanguage = "bos";
Note: To fix your issue the above solution is sufficient. However, to make you code better please see the below suggestions.
In addition to the above I see two more issues:
You are storing translated value in translation instance variable. In case you are using the same Translator object (singleton instance) and the current translation fails, getTranslation() will return the previously translated value.
Why are you initializing expr with the below?
XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
Lastly, every time you are calling getTranslation() the XML is being parsed. Instead, parse it once in init() method and then use it in getTranslation() method.
I have modified your Translator class based on the above points:
package org.openapex.samples.misc.parse.xml;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.io.InputStream;
public class ParseXMLAndTranslate {
public static void main(String[] args) throws Exception{
Translator translator = new Translator();
translator.init();
System.out.println(translator.getTranslation("house","eng", "bos"));
System.out.println(translator.getTranslation("igra","bos", "eng"));
}
private static class Translator {
//String translation = null;
private Document doc;
public void init() throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream is = Translator.class.getResourceAsStream("/resource/glossary.xml");
this.doc = builder.parse(new InputSource(is));
}
String getTranslation(String wordForTransl, String fromLanguage, String toLanguage)
throws XPathExpressionException {
//fromLanguage = "eng";
//toLanguage = "bos";
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
//XPathExpression expr = null; //xpath.compile("//word[eng='house']/bos/text()");
//XPathExpression expr = xpath.compile("//word['" + wordForTransl + "'='" + wordForTransl + "']/bos/text()");
XPathExpression expr = null;
if (fromLanguage == "eng") {
expr = xpath.compile("//word[eng='" + wordForTransl + "']/bos/text()");
} else if (fromLanguage == "bos") {
expr = xpath.compile("//word[bos='" + wordForTransl + "']/eng/text()");
}
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
String translation = null;
/*for (int i = 0; i < nodes.getLength(); i++) {
//System.out.println(nodes.item(i).getNodeValue());
translation = nodes.item(i).getNodeValue();
}*/
if(nodes.getLength() > 0){
translation = nodes.item(0).getNodeValue();
}
//return nodes.item(i).getNodeValue();
if (translation != null) {
return translation;
} else {
return "We are sorry, there is no translation for this word!";
}
}
}
}
Here is the output:
kuca
game

How to get Tag name with normal core java

My Text File:
hibernate-mapping
class name="EmployeeMaster" table="EmployeeMASTER"
id name="empid" type="java.lang.String"
column name="EMPAID"
generator class="assigned"
/generator
/id
/class
/hibernate-mapping
My Expecting Output:
hibernate-mapping
class
id
/id
/class
/hibernate-mapping
Following is the code that do this simply without apis/standard parsers.
File fXmlFile = new File("F:\\Test.hbm.xml");
FileInputStream fis = new FileInputStream(fXmlFile);
String fileContent = "";
while(fis.available() > 0){
fileContent += (char)fis.read();
}
String[] lines = fileContent.split("\n");
for (String string : lines) {
string = string.trim();
String value="";
if(string.startsWith("<")){
if(string.indexOf(" ") == -1)
value = string;
else
value = string.substring(0, string.indexOf(" "));
}
value = value.replace("<", "").replace(">", "");
System.out.println(value);
}
With the help of parser
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.opshub.exceptions.DataValidationException;
public class Test{
public static void main(String[] args) throws DataValidationException, IOException, ParserConfigurationException, SAXException{
File fXmlFile = new File("F:\\checkouts\\current\\Test.hbm.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
org.w3c.dom.Document doc = dBuilder.parse(fXmlFile);
NodeList nodes = doc.getChildNodes();
for(int i=0;i<nodes.getLength();i++){
printElements(nodes.item(i));
}
}
public static void printElements(org.w3c.dom.Node node){
if(node.ELEMENT_NODE != node.getNodeType())
return;
System.out.println(node.getNodeName());
if(node.hasChildNodes()){
for(int i=0;i<node.getChildNodes().getLength();i++){
printElements(node.getChildNodes().item(i));
}
}
System.out.println("/" + node.getNodeName());
}
}

java - xpath to get rows inside a table

I have an html file like: http://scholar.google.gr/citations?user=v9xULZwAAAAJ&hl=el
In this file exist a table with articles. I want to get the first 20 articles (if exist) with xpath.
I try to find fist article:
String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr[2]/td[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
And its Ok! result: Modern information retrieval
for all articles:
String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr/td[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
but do not work
Any Idea?
Than you!
EDIT:
Also I try:
NodeList result = (NodeList)xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr/td[#id='col-title']/a",
docList.get(0), XPathConstants.NODESET);
ArrayList<String>liste = new ArrayList<String>();
for(int i=0; i<result.getLength();i++){
System.out.println(result.item(i).getNodeValue());
liste.add(result.item(i).getNodeName());
}
EDIT 2 All code
Class FileOperation:
package xmlparse;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Document;
public class FileOperations {
private static final String path = "C:\\Users\\Dimitris\\Desktop\\authors";
public ArrayList<Document> getXmlDocumt() {
ArrayList<Document> xmlFileList = new ArrayList<>();
try {
ArrayList<File> listFiles = listFiles(path);
for (File f : listFiles) {
String html = readfile(f.getAbsolutePath());
xmlFileList.add(ConvertHtml2Xml(html) );
}
} catch (IOException ex) {
Logger.getLogger(FileOperations.class.getName()).log(Level.SEVERE, null, ex);
}
return xmlFileList;
}
private ArrayList<File> listFiles(String directoryName) throws IOException {
ArrayList<File> htmlfilelist = new ArrayList<>();
File directory = new File(directoryName);
//get all the files from a directory
File[] fList = directory.listFiles();
for (File file : fList) {
if (file.isFile()) {
htmlfilelist.add(file);
}
}
return htmlfilelist;
}
private String readfile(String file) throws FileNotFoundException, IOException {
String s = "";
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
StringBuilder content = new StringBuilder(1024);
while ((s = br.readLine()) != null) {
content.append(s);
}
//System.out.println(content.toString());
return content.toString();
}
private Document ConvertHtml2Xml(String html) {
TagNode tagNode = new HtmlCleaner().clean(html);
Document doc = null;
try {
doc = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
} catch (ParserConfigurationException ex) {
Logger.getLogger(FileOperations.class.getName()).log(Level.SEVERE, null, ex);
}
return doc;
}
}
Class XpathQueries:
XPath xpath;
ArrayList<Document> docList;
public XpathQueries() {
xpath = XPathFactory.newInstance().newXPath();
FileOperations fo = new FileOperations();
docList = new ArrayList<>(fo.getXmlDocumt());
}
public void getArticle() throws XPathExpressionException {
// String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody//td[1]/a",
// docList.get(0), XPathConstants.STRING);
String str = (String) xpath.evaluate("//*[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
System.out.println(str);
}
}
Try with this:
Object result = xpath.evaluate("//*[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
Thank you for help.
The solution is:
int length;
Object result = xpath.evaluate("//a[contains(#href,'citation_for_view')]", docList.get(0), XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
length = nodes.getLength();
if(length>20){
length=20;
}
for (int i = 0; i < length; i++) {
System.out.println(nodes.item(i).getFirstChild().getNodeValue());
}

JAVA XML PARSING TO SPLIT XML based on object and class tag elements

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

DocumentBuilder.parse(String Uri) is returning the IOException

package com.converter;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.StringTokenizer;
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.SAXParseException;
//import XmlReader.java;
public class XMLReader {
public Float value = 25f;
public XMLReader(){
String parseString = "";
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
URI uri = new URI("http://themoneyconverter.com/USD/rss.xml");
****Document doc = db.parse(uri.toString());****
doc.getDocumentElement().normalize();
NodeList nodeLst = doc.getElementsByTagName("description");
int length = nodeLst.getLength();
for (int s = 0; s < length; s++) {
Node fstNode = nodeLst.item(s);
parseString = fstNode.getTextContent();
if(parseString.contains("Indian Rupee")){
System.out.println(parseString);
StringTokenizer parser = new StringTokenizer(parseString,"=");
parser.nextToken();
StringTokenizer parser1 = new StringTokenizer(parser.nextToken());
value = Float.valueOf(parser1.nextToken());
System.out.println(value);
}
}
} catch (SAXParseException e) {
value = 30f;
e.printStackTrace();
}catch (IOException e) {
value = 33f;
e.printStackTrace();
}catch (Exception e) {
value = 32f;
e.printStackTrace();
}
}
}
This one is working for me outputing:
1 US Dollar = 45.92697 Indian Rupee
45.92697
So I guess you have some network problems accessing the resource. Check your firewall settings, anti virus programs, etc.
Or maybe paste the stack trace here if you need more help ;)
Cheers!

Categories