Reputation: 1349
I'm currently using XPath to get some information from a podcast feed using Java and XPath. I'm trying to read the attribute of a node:
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:atom="http://www.w3.org/2005/Atom/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<channel>
[....]
<itunes:image href="http://icebox.5by5.tv/images/broadcasts/14/cover.jpg" />
[...]
I want to get the value of the href
attribute in <itunes:image>. Currently, I'm using the following code:
private static String IMAGE_XPATH = "//channel/itunes:image/@href";
String imageUrl = xpath.compile(IMAGE_XPATH).evaluate(doc, XPathConstants.STRING).toString();
The result of imageUrl is null. What happens in the code? Do I have an error in the XPath code, or in the Java code?
Thanks! :)
Upvotes: 1
Views: 6857
Reputation: 776
Disable namespace awarness:
DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
xmlFact.setNamespaceAware(false);
Your xpath expression should look like this now:
"//channel/image/@href"
If you need to use it as namespace aware, just implement your own NameSpaceContext, should look like this:
NamespaceContext ctx = new ItunesNamespaceContext();
XPathFactory xpathFact = XPathFactory.newInstance();
XPath xpath = xpathFact.newXPath();
xpath.setNamespaceContext(ctx);
String IMAGE_XPATH = "//channel/itunes:image/@href";
String imageUrl = path.compile(IMAGE_XPATH).evaluate(doc,XPathConstants.STRING).toString();
EDIT: Here is a test code that proves my point:
String a ="<?xml version=\"1.0\" encoding=\"UTF-8\"?><rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\" xmlns:admin=\"http://webns.net/mvcb/\" xmlns:atom=\"http://www.w3.org/2005/Atom/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\" xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\" version=\"2.0\"><channel><itunes:image href=\"http://icebox.5by5.tv/images/broadcasts/14/cover.jpg\" /></channel></rss>";
DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance();
xmlFact.setNamespaceAware(false);
DocumentBuilder builder = xmlFact.newDocumentBuilder();
XPathFactory xpathFactory = XPathFactory.newInstance();
String expr = "//channel/image/@href";
XPath xpath = xpathFactory.newXPath();
Document doc = builder.parse(new InputSource(new StringReader(a)));
String imageUrl = (String) xpath.compile(expr).evaluate(doc ,XPathConstants.STRING);
System.out.println(imageUrl);
The output is:
http://icebox.5by5.tv/images/broadcasts/14/cover.jpg
Upvotes: 4
Reputation: 6793
The XPath should include the root element, so rss/channel/itunes:image/@href.
Alternatively, you could start the xpath with a // so that all levels are searched for the xpath (//channel/itunes:image/@href) but if the root will always be the same it is more efficient to use the first option.
Upvotes: 0