XPath和命名空间 - 查询不给出结果

时间:2018-03-14 16:43:58

标签: java xml xpath

不使用命名空间,XPath示例运行正常。列表已打印。添加命名空间后,不会返回任何结果。

如何正确使用命名空间和XPath?

我的样本(最小化)xml文件是:

<?xml version="1.0" encoding="UTF-8"?>
<nodespace:Employees xmlns:nodespace="my_unique_namespace_name">
    <nodespace:Employee id="1">
        <nodespace:age>29</nodespace:age>
        <nodespace:name>Pankaj</nodespace:name>
        <nodespace:gender>Male</nodespace:gender>
        <nodespace:role>Java Developer</nodespace:role>
    </nodespace:Employee>
    <nodespace:Employee id="2">
        <nodespace:age>35</nodespace:age>
        <nodespace:name>Lisa</nodespace:name>
        <nodespace:gender>Female</nodespace:gender>
        <nodespace:role>CEO</nodespace:role>
    </nodespace:Employee>
</nodespace:Employees>

XPath Java源代码是:

public class XpathNamespaceTest {
    public static final String PREFIX_NAME = "bdn";
    public static final String NODESPACE_UNIQUE_NAME = "nodespace";
    public static void main(String[] args) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        DocumentBuilder builder;
        Document doc = null;
        try {
            ClassLoader classLoader = new XpathNamespaceTest().getClass().getClassLoader();
            URL resource = classLoader.getResource("employees_namespace.xml");
            File file = new File( resource.getFile());
            builder = factory.newDocumentBuilder();
            doc = builder.parse(file);
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath xpath = xpathFactory.newXPath();
            xpath.setNamespaceContext(new NamespaceContext() {
                @Override
                public Iterator getPrefixes(String arg0) { return null; }
                @Override
                public String getPrefix(String ns) {
                    if(ns.equals(NODESPACE_UNIQUE_NAME)) {
                        return PREFIX_NAME;
                    }
                    return null;
                }
                @Override
                public String getNamespaceURI(String arg0) {
                    if (PREFIX_NAME.equals(arg0)) {
                        return NODESPACE_UNIQUE_NAME;
                    }
                    return null;
                }
            });

            List<String> names = getEmployeeNameWithAge(doc, xpath, 30);
            System.out.println("Employees with 'age>30' are:" + Arrays.toString(names.toArray()));
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
    }
    private static List<String> getEmployeeNameWithAge(Document doc, XPath xpath, int age) {
        List<String> list = new ArrayList<>();
        try {
            XPathExpression expr = xpath.compile("/bdn:Employees/bdn:Employee[bdn:age>" + age + "]/bdn:name/text()");
            NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
            for (int i = 0; i < nodes.getLength(); i++) list.add(nodes.item(i).getNodeValue());
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return list;
    }
}

1 个答案:

答案 0 :(得分:2)

命名空间URI为my_unique_namespace_name,因此您需要

public static final String NODESPACE_UNIQUE_NAME = "my_unique_namespace_name";