I found the following easy solution to extracting values from XML file.
import java.io.IOException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
public class XPathExample {
public static void main(String[] args)
throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("c:/temp/books.xml");
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr
= xpath.compile("//book[author='Neal Stephenson']/title/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());
}
}
}
This uses xpath to extract all books title where the author is Neal Stephenson from the following xml
<inventory>
<book year="2000">
<title>Snow Crash</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553380958</isbn>
<price>14.95</price>
</book>
<book year="2005">
<title>Burning Tower</title>
<author>Larry Niven</author>
<author>Jerry Pournelle</author>
<publisher>Pocket</publisher>
<isbn>0743416910</isbn>
<price>5.99</price>
</book>
<book year="1995">
<title>Zodiac</title>
<author>Neal Stephenson</author>
<publisher>Spectra</publisher>
<isbn>0553573862</isbn>
<price>7.50</price>
</book>
<!-- more books... -->
</inventory>
Now this works fine on JDK5 but i am using jdk 1.4
Can this be converted to the java 1.4 equivalent?
All i am trying to do is extract a value from an xml element. For example, in the above xml, i just want something that is the equivalent of getElementByTag("title").
Thanks
Quick google resulted in links like this and this which confirm that JAXP can be downloaded separately and run on top of JDK 1.4.2. You might run into configuration problems as mentioned in the apache link. Good luck!
Related
This is my XML file:
<Root>
<Id>1</Id>
<Title>My title</Title>
<More>
<Extension>Ex</Extension>
<Extra>Extra info</Extra>
<Comments>
<Comment date="2018-11-26T06:00:00+02:00">Hey, this is my comment</Comment>
<Comment date="2017-11-26T06:00:00+02:00">Hey, this is my comment</Comment>
<Comment date="2016-11-26T06:00:00+02:00">Hey, this is my comment</Comment>
<Comment date="2011-11-26T06:00:00+02:00">Hey, this is my comment</Comment>
</Comments>
</More>
</Root>
I am only interested in <Comment> data.
My current approach is using JaxB unmarshalling and having classes Root.java, More.java, Comments.java which contains class Comment.java. So it's kinda messy.
I have no problem doing it this way, but I would like to know if there is any method that let's you go straight for the <Comment> data and having only 1 class Comment.java for it?
If you only want to get all the comment tags from the XML file, you may try out following approach,
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.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ReadComments {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
File xml = new File("D:/data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
Document doc = docBuilder.parse(xml);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("Comment");
for (int i= 0; i< nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
System.out.printf("Comment : %s | Date : %s\n", node.getTextContent(), element.getAttribute("date"));
}
}
}
}
Output :
Comment : Hey, this is my comment | Date : 2018-11-26T06:00:00+02:00
Comment : Hey, this is my comment | Date : 2017-11-26T06:00:00+02:00
Comment : Hey, this is my comment | Date : 2016-11-26T06:00:00+02:00
Comment : Hey, this is my comment | Date : 2011-11-26T06:00:00+02:00
Note that this is just an example to explain about getting details of specific tags, you will have to modify this code as per for your need.
I am not able to display the value of xml tag using namespace - tag with colon.
When there are no colons in tags, code works perfectly, but as soon I want to display a tag which contains colon, program doesnt throw any error, only doesn`t show any value.
Here is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:inv="http://www.w3schools.com/daco" xmlns:lst="http://www.esa.int/safe/sentinel-1.0" version="1.0">
<lst:howto>
<topic id="1">
<nieco>
<lst:title>Java</lst:title>
</nieco>
</topic>
</lst:howto>
</xsl:stylesheet>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:lst="http://www.esa.int/safe/sentinel-1.0" version="1.0">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:template match="/">
topic
<xsl:for-each select="//nieco">
<xsl:value-of select="lst:title" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
and Java:
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
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.transform.stream.StreamSource;
import org.w3c.dom.Document;
class XMLtoCsVConversion2 {
public static void main(String args[]) throws Exception {
File stylesheet = new File("C:/java/howto.xsl");
File xmlSource = new File("C:/java/howto.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File("xyz.csv"));
transformer.transform(source, outputTarget);
System.out.println("done");
}
}
Codes really simplified to find the cause of the problem, but I was not able to figure it out.
If I would remove lst: from tag in xml and from xsl, it would work, as soon there is colon, program doesn`t show any value.
But XML we receive contain plenty of tags with colon, so I would a solution to this problem.
Please if you have any idea where could be the problem, please let me know :)
Expected output:
topic
Java
Try this;
public static void main(String args[]) throws Exception {
File stylesheet = new File("C:/java/howto.xsl");
File xmlSource = new File("C:/java/howto.xml");
// DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// DocumentBuilder builder = factory.newDocumentBuilder();
// Document document = builder.parse(xmlSource);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance()
.newTransformer(stylesource);
//Source source = new DOMSource(document);
Source source = new StreamSource(xmlSource);
Result outputTarget = new StreamResult(new File("C:/java/xyz.csv"));
transformer.transform(source, outputTarget);
System.out.println("done");
}
i'm trying to get result of expression of xpath , my xml file is like this :
<?xml version="1.0"?>
<all>
<test1>
</test1>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
</catalog>
</all>
and my java code is :
public class xpath_test {
public static void main(String[] args) throws XPathExpressionException, SAXException, IOException, ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = (Document) builder.parse("C:\\Users\\HC\\Desktop\\dataset\\book.xml");
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/all/catalog");
NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
}
}
i got an exception :
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl cannot be cast to org.jdom2.Document
especially in this line Document doc = (Document) builder.parse("C:\\Users\\HC\\Desktop\\dataset\\book.xml");
knowing that i import import org.jdom2.Document;
try to use the standard interface
import org.w3c.dom.document
instead of
import org.jdom2.Document
I have XML file like this:
<catalog>
<category>
<books>
<book>
<id>book1</id>
<description>short description</description>
<pages>number of pages</pages>
<author>Anonymous</author>
<name>Book title</name>
</book>
<book>
<id>book2</id>
<description>short description</description>
<pages>number of pages</pages>
<author>Anonymous</author>
<name>Book title</name>
</book>
</books>
</category>
<category>
<books>
<book>
<id>book3</id>
<description>short description</description>
<pages>number of pages</pages>
<author>Anonymous</author>
<name>Book title</name>
</book>
</books>
</category>
</catalog>
And I need an ArrayList with Categories and ArrayList with Books. Here are my Book and Category classes:
public class Book
{
private String id;
private String description;
private String pages;
private String author;
private String name;
}
public class Category {
private ArrayList<Book> books;
private String name;
}
What is the easiest way to do this? Using only android libraries and stuff would be better than using some libraries not for commercial use for my task. I tried some DOM parsers, but it didn't work good.
Actually it can easily be done using dom parser. Here is a stand alone java program to parse your XML file. I am printing values in standard output you can modify it to use in your android application.
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
File fXmlFile = new File("books");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
// iterate through <category> tags
NodeList categoryList = doc.getElementsByTagName("category");
for (int categoryNo=0;categoryNo<categoryList.getLength();categoryNo++) {
Element categoryNode = (Element)categoryList.item(categoryNo);
System.out.println("Category No " +categoryNo);
//iterate through <books> tags
NodeList booksList = categoryNode.getElementsByTagName("books");
for (int booksNo=0;booksNo<booksList.getLength();booksNo++) {
Element books = (Element)booksList.item(0);
// iterate through <book> tags
NodeList bookList = books.getElementsByTagName("book");
for(int bookNo=0;bookNo<bookList.getLength();bookNo++) {
Element bookElement = (Element)bookList.item(bookNo);
System.out.println(bookElement.getElementsByTagName("id").item(0).getTextContent());
System.out.println(bookElement.getElementsByTagName("description").item(0).getTextContent());
System.out.println(bookElement.getElementsByTagName("pages").item(0).getTextContent());
System.out.println(bookElement.getElementsByTagName("author").item(0).getTextContent());
System.out.println(bookElement.getElementsByTagName("name").item(0).getTextContent());
}
}
}
}
}
Have a look at android xml pull parser, this page has examples too
(it is a SAX parser)
I have this sample xml.
Each row has an id field, it has values as bits.
And I want to find in this file with bitwise-and operator but I don't know if this is possible.
I read about the operator '&' in javascript or comand BITAND in Oracle but nothing in xml o xpath.
This is the example code in java and xpath:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Util implements java.io.Serializable {
static public String filter_xpath_bitand (int var_tipo)
NodeList nodeList = null;
Element element = null;
try {
XPath xpath = XPathFactory.newInstance().newXPath();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File(fileXML));
nodeList = (NodeList)xpath.evaluate("/test/row[(id & \""+ var_tipo +"\") > 1]", document.getDocumentElement(), XPathConstants.NODESET);
} catch (Exception e) {
System.out.println("*** filterXML --> exception: " + e.toString());
}
}
}
From looking at the XPATH reference there is no such thing as bitwise operations.
You could work around that though by making use of existing operations (mod etc).
See here for a related question.
EDIT:
Sample xml:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<row>
<id>32</id>
<titulo>yellow</titulo>
</row>
<row>
<id>16</id>
<titulo>green</titulo>
</row>
<row>
<id>8</id>
<titulo>red</titulo>
</row>
<row>
<id>1</id>
<titulo>blue</titulo>
</row>
<row>
<id>2</id>
<titulo>white</titulo>
</row>
<row>
<id>4</id>
<titulo>black</titulo>
</row>
</test>
Java code:
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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 BitWiseXPathTest {
public static void main(String[] args) {
Set<String> selectedColors = new HashSet<String>();
int var_tipo = 33;
try {
XPath xpath = XPathFactory.newInstance().newXPath();
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
String fileXML = "bitwise.xml";
Document document = builder.parse(new File(fileXML));
String evalStr = "/test/row/id";
NodeList nodeList = (NodeList)xpath.evaluate(evalStr, document.getDocumentElement(), XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node aNode = nodeList.item(i);
if( (Integer.parseInt(aNode.getTextContent()) & var_tipo) > 0) {
//System.out.println("color: "+aNode.getNextSibling().getNextSibling().getTextContent());
selectedColors.add(aNode.getNextSibling().getNextSibling().getTextContent());
}
}
} catch (Exception e) {
System.out.println("*** filterXML --> exception: " + e.toString());
}
System.out.println(selectedColors);
}
}
Again, XPATH doesn't seem to have a bitwise operation. You could move the operation outside of XPATH and do it in Java as a workaround.