我的XPath表达式不会在Java中选择任何内容

时间:2013-05-13 20:36:58

标签: java xpath

我正在用Java评估一个XPath表达式,它应该只返回一个String值。
但是,我得到的只是一个空白值。

SSCCE

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

<?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:

我原本希望在那里看到 John 。有人可以告诉我出了什么问题吗?

2 个答案:

答案 0 :(得分:2)

这是我们许多人犯的错误! Xpath对名称空间敏感。您的XML文件包含命名空间元素,XPath中需要这些命名空间。在XML文件中,您可以使用默认命名空间,但不能在XPath中使用。

尝试

"/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']"

它应该有用。

您的系统可能允许在XPath中使用名称空间前缀。这些不能为空。一个例子可能是:

"/a:people/a:student[@scholarship='yes']/a:name"

如何映射命名空间前缀(a)取决于软件。请注意,只要映射了任何前缀,它都会执行。

答案 1 :(得分:1)

我将Jaxen与Jdom2一起使用,发现这有用:http://www.edankert.com/defaultnamespaces.html

使其工作的一种方法是为默认命名空间定义前缀。在这里我将其命名为默认值(您可以根据需要为前缀命名。)然后在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);