Thanks in advance.
I have a xml with 2 default namespace at rootlevel and then as element level.
<?xml version="1.0" encoding="UTF-8"?>
<Msg xmlns="http://www.geological.com">
<header>
<date>08-08-2021</date>
<jur>US</jur>
</header>
<Demographic xmlns="urn:com.test:009">
<geoData>
<id>DL89716</id>
<name>North</name>
</geoData>
</Demographic>
</Msg>
I am using Java DOM parser to read this xml and fetch value of "id".
Still I am getting value as null
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
dbFactory.setNamespaceAware(true);
document = dBuilder.parse(new InputSource(new StringReader(xmlPayLoad)));
document.normalize();
XPathEvaluator xPathObj = (XPathEvaluator)XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON).newXPath();
xPathObj.setNamespaceContext(new MyNameSpace());
xPathObj.getStaticContext().setDefaultElementNamespace("http://www.geological.com");
XPathExpression expr = xPathObj.compile(xpath);
Object result = expr.evaluate(document, XPathConstants.NODESET);
NodeList nodeList = (NodeList) result;
private static class MyNameSpace implements NamespaceContext {
//The lookup for the namespace uris is delegated to the stored document.
public String getNamespaceURI(String prefix) {
if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
return null;
} if("ns".equals(prefix)){
return "urn:com.test:009";
}
}
public String getPrefix(String namespaceURI) {
return sourceDocument.lookupPrefix(namespaceURI);
}
#SuppressWarnings("rawtypes")
public Iterator getPrefixes(String namespaceURI) {
return null;
}
}
Here is a fully functional example:
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
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 java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class NamespacesExample {
private static String xmlPayLoad =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg xmlns=\"http://www.geological.com\">\n" +
" <header>\n" +
" <date>08-08-2021</date>\n" +
" <jur>US</jur>\n" +
" </header>\n" +
" <Demographic xmlns=\"urn:com.test:009\">\n" +
" <geoData>\n" +
" <id>DL89716</id>\n" +
" <name>North</name>\n" +
" </geoData>\n" +
" </Demographic>\n" +
"</Msg>";
public static void main(String[] args) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
dbFactory.setNamespaceAware(true);
dBuilder = dbFactory.newDocumentBuilder();
Document document = dBuilder.parse(new InputSource(new StringReader(xmlPayLoad)));
final Map<String, String> ns = new HashMap<>();
ns.put("geo", "http://www.geological.com");
ns.put("test", "urn:com.test:009");
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new MyNameSpace(ns));
XPathExpression expr = xpath.compile("/geo:Msg/test:Demographic/test:geoData/test:id/text()");
String result = (String) expr.evaluate(document, XPathConstants.STRING);
System.out.println("Result: " + result);
} catch (ParserConfigurationException | IOException | XPathExpressionException | SAXException e) {
e.printStackTrace();
}
}
private static class MyNameSpace implements NamespaceContext {
private final Map<String, String> ns;
MyNameSpace(Map<String, String> ns) {
this.ns = new HashMap<>(ns);
this.ns.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
this.ns.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
}
#Override
public String getNamespaceURI(String prefix) {
if(prefix == null) {
throw new IllegalArgumentException();
}
final String uri = ns.get(prefix);
return uri == null ? XMLConstants.NULL_NS_URI : uri;
}
#Override
public String getPrefix(String namespaceURI) {
throw new UnsupportedOperationException();
}
#Override
public Iterator getPrefixes(String namespaceURI) {
throw new UnsupportedOperationException();
}
}
}
Some remarks:
The order of these statements is significant. Otherwise there is no namespace awareness:
dbFactory.setNamespaceAware(true);
dBuilder = dbFactory.newDocumentBuilder();
Why do you use XPathEvaluator? There is no need for that. Using the interface XPath is enough.
What is NamespaceConstant.OBJECT_MODEL_SAXON? At least in this example, we don't need it.
With my generic NamespaceContext implementation you can use a simple Map<String, String> to define the namespace prefixes for XPATH evaluation.
Dedicated prefixes should be used for each namespace used in the XML, regardless of how the namespace is declared in the XML document.
Then you can use this XPATH expression to extract the id: /geo:Msg/test:Demographic/test:geoData/test:id/text()
Output is:
Result: DL89716
I would use //*:id as the path if you know there is a single id element you are looking for, or at least there are not several id elements from different namespaces and you want to select only those from one namespace.
If you only want to select those from one namespace (e.g. urn:com.test:009) then set that as the default namespace and you can simply use //id or //Demographic/geoData/id.
Only if you really need to select elements from different namespaces you need to bind prefixes.
With the Java 8 built-in JAXP XPathFactory and a not namespace aware DocumentBuilderFactory the following also works for me to select the id element node as then the default namespace declarations are ignored when building the DOM tree:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(false);
DocumentBuilder jaxpDocumentBuilder = documentBuilderFactory.newDocumentBuilder();
Document domDoc = jaxpDocumentBuilder.parse(new File("sample1.xml"));
XPathFactory jaxpXPathFactory = XPathFactory.newInstance();
Node resultDomNode = (Node)jaxpXPathFactory.newXPath().evaluate("/Msg/Demographic/geoData/id", domDoc, XPathConstants.NODE);
I think in your original code, once you build a namespace aware DOM, with your use of the Saxon API, you could get away with setting
xPathObj.getStaticContext().setUnprefixedElementMatchingPolicy(UnprefixedElementMatchingPolicy.ANY_NAMESPACE);
and not to set up any namespace context nor default element namespace.
The other way with Saxon 10 and XPath to match elements in any namespace with selectors like id I could find is to dive into its low-level API to mix it with the s9api:
Processor processor = new Processor(false);
DocumentBuilder docBuilder = processor.newDocumentBuilder();
XdmNode input = docBuilder.build(new File("sample1.xml"));
NodeInfo contextItem = input.getUnderlyingNode();
XPathEvaluator xpathEvaluator = new XPathEvaluator(processor.getUnderlyingConfiguration());
IndependentContext independentContext = new IndependentContext();
independentContext.setUnprefixedElementMatchingPolicy(UnprefixedElementMatchingPolicy.ANY_NAMESPACE);
xpathEvaluator.setStaticContext(independentContext);
XPathExpression expression = xpathEvaluator.createExpression("/Msg/Demographic/geoData/id");
NodeInfo resultInfo = (NodeInfo) expression.evaluateSingle(expression.createDynamicContext(contextItem));
XdmNode resultNode = new XdmNode(resultInfo);
System.out.println(resultNode);
Related
I have an XML file having many nodes with attributes as well as child elements with same field name:
<doc>
<str name="eventId">54605a22aa7d649f085242e3</str>
<arr name="toolLogExt">
<str>.xls.lck</str>
<str>.xls.lck</str>
<str>.xls.lck</str>
</arr>
<arr name="messageTech">
<str>Java run-time error</str>
<str>Java run-time error</str>
<str>Java run-time error</str>
</arr>
<arr name="messageId">
<str>546066238d194b463e365194</str>
<str>546090b48d194b463e365196</str>
<str>546090f78d194b463e365198</str>
</arr>
<arr name="eventType">
<str>Run-time error</str>
</arr>
<str name="type">acme</str>
<arr name="messageSolution">
<str>XXXXX</str>
<str>YYYYY</str>
<str>ZZZZZ</str>
</arr>
<arr name="toolID">
<str>54605d7d8d194b463e36517e</str>
<str>54605d7d8d194b463e36517e</str>
<str>54605d7d8d194b463e36517e</str>
</arr>
</doc>
I have read many posts on Stack-Overflow but I haven't come up across an XML Format like this. One of the regular ways is to do individual string processing after getting every node with their respective attributes and maintain a count to construct a Document Model later. However, is there a direct method to obtain all the fields?
Edit1
My approach so far....
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ParseSAX extends DefaultHandler {
List<String> errorsLister;
String inpXMLFileName;
public ParseSAX(String xmlFileName) {
this.inpXMLFileName = xmlFileName;
errorsLister = new ArrayList<String>();
parseDocument();
}
private void parseDocument() {
// parse
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(inpXMLFileName, this);
} catch (ParserConfigurationException e) {
System.out.println("ParserConfig error");
} catch (SAXException e) {
System.out.println("SAXException : xml not well formed");
} catch (IOException e) {
System.out.println("IO error");
}
}
#Override
public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
if (elementName.equalsIgnoreCase("str")) {
String temp = (attributes.getValue("eventId"));
// This would give me the event ID
// Further usage
}
// if current element is publisher
if (elementName.equalsIgnoreCase("arr")) {
String temp = attributes.getValue("messageTech");
}
}
#Override
public void endElement(String s, String s1, String element) throws SAXException {
// Can't seem to figure out what to do here!!!
}
public static void main(String[] args) {
new ParseSAX("..//input2.xml");
// To individually get field values having attribute names
// I know we can do this ....
/**
try {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc;
dDoc = builder.parse("..//input2.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
String string = (String) xPath.evaluate("/response/result[#name='response']/doc/arr[#name='messageId']/str", dDoc, XPathConstants.STRING);
} catch (SAXException | IOException | XPathExpressionException | ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
**/
}
}
You can read elements inside any XML tag using below function.
public class XmlFileReader{
public NodeList readXML(String filePath, String tagName, String subTagName, String tagAttr) {
try {
// Get XML file object.
File fXmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
NodeList nodeList = doc.getElementsByTagName(tagName);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if (element.getAttribute("name").equalsIgnoreCase(tagAttr)) {
NodeList elementsByTagName = element.getElementsByTagName(subTagName);
return elementsByTagName ;
}
}
}
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
LogManager.fatal(stack.toString(), ReadTemplate.class.getName());
}
return elementsByTagName;
}
}
Function Call :
XmlFileReader xmlFileReader = new XmlFileReader();
NodeList toolLogExtChilds = xmlFileReader.readXML("Path to XML file",
"arr", "str", "toolLogExt");
<?xml version="1.0" encoding="UTF-8"?>
<JDF DescriptiveName="DescriptiveName" ID="n0001" JobID="1101-CCC-0" JobPartID="1" ProjectID="">
<Comment Name="Materialnummer">XXXXXXX</Comment>
<NodeInfo LastEnd="2014-03-12T18:00:00+01:00">
<EmployeeRef rRef="EMPCSR"/>
</NodeInfo>
<CustomerInfo CustomerID="1740">
</CustomerInfo>
<ResourcePool>
</ResourcePool>
<ResourceLinkPool>
</ResourceLinkPool>
<JDF Category="FinalImaging" ID="n0002" Status="Waiting" Type="ProcessGroup" Types="XXX">
<ResourcePool>
</ResourcePool>
<ResourceLinkPool>
</ResourceLinkPool>
</JDF>
<JDF ID="n0002" Status="Waiting" Type="ProcessGroup" Types="PrePressPreparation">
<ResourcePool>
</ResourcePool>
<ResourceLinkPool>
</ResourceLinkPool>
</JDF>
</JDF>
How do I get the root element value. For this example I want to get the DescriptiveName,ID,JobID and ProjectID. I managed to read other values but stuck in root emlement. Please advice.
EDITED
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
//System.out.println("*************************");
String expression = "/JDF";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
A sample here :
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class Main {
public static void main(String[] argv) throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setExpandEntityReferences(false);
Document doc = factory.newDocumentBuilder().parse(new File("filename"));
Element root = null;
NodeList list = doc.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
root = (Element) list.item(i);
break;
}
}
root = doc.getDocumentElement();
}
}
You can get the attributes from root object
this is the xml file
please how to parse the tag author example we dont know how many author for each inproceeding ?
<?xml version="1.0" encoding="ISO-8859-1"?>
<dblp>
<inproceedings mdate="2014-01-18" key="series/sci/AzzagL13">
<author>Hanane Azzag</author>
<author>Mustapha Lebbah</author>
<title>A New Way for Hierarchical and Topological Clustering.</title>
<pages>85-97</pages>
<year>2011</year>
<booktitle>EGC (best of volume)</booktitle>
<ee>http://dx.doi.org/10.1007/978-3-642-35855-5_5</ee>
<crossref>series/sci/2013-471</crossref>
<url>db/series/sci/sci471.html#AzzagL13</url>
</inproceedings>
<inproceedings mdate="2014-01-18" key="series/sci/RabatelBP13">
<author>Julien Rabatel</author>
<author>Sandra Bringay</author>
<author>Pascal Poncelet</author>
<title>Mining Sequential Patterns: A Context-Aware Approach.</title>
<pages>23-41</pages>
<year>2011</year>
<booktitle>EGC (best of volume)</booktitle>
<ee>http://dx.doi.org/10.1007/978-3-642-35855-5_2</ee>
<crossref>series/sci/2013-471</crossref>
<url>db/series/sci/sci471.html#RabatelBP13</url>
</inproceedings>
</dblp>
Use Xpath, it's fast and powerfull , these lines for your example return 5 lines
Code:
final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream("input.xml"));
final XPath xPath = XPathFactory.newInstance().newXPath();
final NodeList nodeList = (NodeList) xPath.compile("//author").evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getFirstChild().getNodeValue());
}
Displays:
Hanane Azzag
Mustapha Lebbah
Julien Rabatel
Sandra Bringay
Pascal Poncelet
Following code parse using apache digester which is commonly used while parsing in real projects. Nice one from apache community
// Updated code as per you need.
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.Rules;
import org.xml.sax.InputSource;
public class Parsing {
public static void main(String[] args) throws Exception{
InputStream data = new FileInputStream("E:\\workspace\\trunk\\Parsing\\src\\data.xml");
byte[] b = new byte[data.available()];
// data.read(b);
Digester digester = new Digester();
//Genearting Array list while encountering dblp xpath
digester.addObjectCreate("dblp", HashMap.class);
digester.addObjectCreate("dblp/inproceedings", ArrayList.class);
//Calling add method while encountering author xpath
AuthorRule rule = new AuthorRule();
digester.addRule("dblp/inproceedings/author", rule);
digester.addRule("dblp/inproceedings/title", rule);
digester.addRule("dblp/inproceedings", rule);
HashMap parsedData = (HashMap) digester.parse(data);
Iterator<Entry<String, ArrayList>> dataItr = parsedData.entrySet().iterator();
while(dataItr.hasNext()){
Entry<String, ArrayList> entry = dataItr.next();
System.out.println("Title : " + entry.getKey() + ", Authors" + entry.getValue().toString());
}
}
private static class AuthorRule extends Rule{
String currentTitle = "";
#Override
public void body(String namespace, String name, String text)
throws Exception {
HashMap object = (HashMap) digester.peek(1);
ArrayList authors = (ArrayList) digester.peek(0);
if(name.equals("title")){
currentTitle = text;
}
else if(name.equals("author")){
authors.add(text);
}
}
#Override
public void end(String namespace, String name) throws Exception {
HashMap object = (HashMap) digester.peek(1);
ArrayList authors = (ArrayList) digester.peek(0);
if(name.equals("inproceedings")){
object.put(currentTitle, authors);
}
}
}
}
output::
Title : A New Way for Hierarchical and Topological Clustering., Authros[Hanane Azzag, Mustapha Lebbah]
Title : Mining Sequential Patterns: A Context-Aware Approach., Authros[Julien Rabatel, Sandra Bringay, Pascal Poncelet]
there are number of ways, e.g. via DOM:
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XmlAuthorReader {
public static void main(String argv[]) {
try {
File fXmlFile = new File(<filePath>);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
NodeList nList = doc.getElementsByTagName("author");
System.out.println(nList.getLength()+ " author(s) found");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("Author: " + nNode.getTextContent());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
you can find more variants here: http://www.mkyong.com/tutorials/java-xml-tutorials/
I need to be able to pull out the USD conversion from Euro using this xml:
http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
I've gotten it to work if I manually download the xml and parse to the data I need from there, but I'm not sure how to grab it directly from the url.
Thank you
If i understand well, you are having trouble obtaining the xml content directly from the URL, is that right?
If so, this might help you.
// the SAX way:
XMLReader myReader = XMLReaderFactory.createXMLReader();
myReader.setContentHandler(handler);
myReader.parse(new InputSource(new URL(url).openStream()));
// or if you prefer DOM:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new URL(url).openStream());
It applies well to a service or stand alone context, but if you are trying to access the XML from your WEB tier you might consider an AJAX approach.
Cant make any easier than that:
package com.danielmarreco;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.net.URL;
public class Main {
public static void main(String[] args) {
try {
InputStream is = new URL("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml").openStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
NodeList nodeList = doc.getElementsByTagName("Cube");
for (int i = 0; i < nodeList.getLength(); i ++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
if(element.getAttribute("currency").equals("BRL"))
System.out.println("1 EUR = " + element.getAttribute("rate") + " BRL");
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I have a problem in printing the value of an attribute existing in a node in a given XML file.I use that code and it compiled correctly but didn't print anything:
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//rss/channel/yweather:location/#city");
Object result = expr.evaluate(doc, XPathConstants.STRING);
System.out.println(result);
and the XML file is :
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>
<title>Yahoo! Weather - Sunnyvale, CA</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Sunnyvale__CA/*http://weather.yahoo.com/forecast/USCA1116_f.html</link>
<description>Yahoo! Weather for Sunnyvale, CA</description>
<language>en-us</language>
<lastBuildDate>Fri, 18 Dec 2009 9:38 am PST</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Sunnyvale" region="CA" country="United States"/>
<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
</channel>
</rss>
The following code works with the namespace reference in the xpath. The key points are implementing the NamespaceContext and calling domFactory.setNamespaceAware(true)...
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
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.w3c.dom.Document;
public class Demo
{
public static void main(String[] args)
{
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
try
{
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document dDoc = builder.parse("c:\\path\\to\\xml\\file.xml");
XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new UniversalNamespaceResolver(dDoc));
String query = "//rss/channel/yweather:location/#city";
XPathExpression expr = xPath.compile(query);
Object result = expr.evaluate(dDoc, XPathConstants.STRING);
System.out.println(result);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static class UniversalNamespaceResolver implements NamespaceContext
{
private Document sourceDocument;
public UniversalNamespaceResolver(Document document)
{
sourceDocument = document;
}
public String getNamespaceURI(String prefix)
{
if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX))
return sourceDocument.lookupNamespaceURI(null);
else
return sourceDocument.lookupNamespaceURI(prefix);
}
public String getPrefix(String namespaceURI)
{
return sourceDocument.lookupPrefix(namespaceURI);
}
public Iterator getPrefixes(String namespaceURI)
{
return null;
}
}
}
Be sure to change the file path before running.