Reputation: 24998
I was evaluating an XPath expression in Java and it was supposed to return just a single String
value in return.
However, all I get is a blank value.
import javax.xml.xpath.*;
import java.io.*;
import org.xml.sax.*;
public class XPathBasic{
public static void main(String[] args){
XPathFactory factory;
XPath xPath;
XPathExpression xPathExpressionCompiled;
String xPathExpressionString;
File xmlFile;
InputSource inputSource;
try{
factory = XPathFactory.newInstance();
xPath = factory.newXPath();
xPathExpressionString = "/people/student[@scholarship='yes']/name";
xPathExpressionCompiled = xPath.compile(xPathExpressionString);
xmlFile = new File("helloWorld.xml");
inputSource = new InputSource(new FileInputStream(xmlFile));
String name = xPathExpressionCompiled.evaluate(inputSource);
if(name != null){
System.out.println("Name of the student is: " + name);
}else{
System.out.println("Error");
}
}catch(XPathExpressionException e){
System.out.println("There seems to be an error with your expression: " + e.getMessage());
}catch(IOException e){
}catch(Exception e){
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<people xmlns="http://www.cmu.edu/ns/blank"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.cmu.edu/ns/blank student.xsd">
<student scholarship="yes">
<name>John</name>
<course>Computer Technology</course>
<semester>6</semester>
<scheme>E</scheme>
</student>
<student scholarship="no">
<name>Foo</name>
<course>Industrial Electronics</course>
<semester>6</semester>
<scheme>E</scheme>
</student>
</people>
Name of student is:
I was expecting to see John there. Can someone please tell me what went wrong ?
Upvotes: 2
Views: 276
Reputation: 1065
I used Jaxen with Jdom2 and found this helpful: http://www.edankert.com/defaultnamespaces.html
One way to make it work is to define a prefix for your default namespace. Here I named it default. (You can name the prefix anything you want.) Then reference the new prefix in your xpath.
Namespace nameSpaceDefault =
Namespace.getNamespace("default", "http://www.cmu.edu/ns/blank");
Namespace nameSpaceXsi =
Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
nameSpaces.add(nameSpaceDefault);
nameSpaces.add(nameSpaceXsi);
String xpath = "/default:people/default:student[@scholarship='yes']/default:name/text()";
XPathExpression<Text> xpathExpression = XPathFactory.instance().
compile(xpath, Filters.text(), null, nameSpaces);
//Jdom2 document
Document document = ...;
//Evaluate xpath
List<Text> textValues = xpath.evaluate(document);
Upvotes: 1
Reputation: 38043
This is a mistake that many of us make! Xpath is sensitive to namespaces. Your XML file contains namespaced elements and these namespaces are required in the XPath. In the XML file you can use a default namespace, but not in XPath.
try
"/people[namespace-uri()='http://www.cmu.edu/ns/blank']/student[namespace-uri()='http://www.cmu.edu/ns/blank' and @scholarship='yes']/name[namespace-uri()='http://www.cmu.edu/ns/blank']"
and it should work.
Your system probably allows namespaces prefixes in the XPath. These cannot be empty. An example might be:
"/a:people/a:student[@scholarship='yes']/a:name"
How you map the namespace prefix (a) depends on the software. Note any prefix will do as long as it is mapped.
Upvotes: 2