0

我想在 Java 中使用 XPath 读取 XML 数据。

我有下一个名为的 XML 文件MyXML.xml

<?xml version="1.0" encoding="iso-8859-1" ?>
<REPOSITORY xmlns:LIBRARY="http://www.openarchives.org/LIBRARY/2.0/"
            xmlns:xsi="http://www.w3.prg/2001/XMLSchema-instance"
            xsi:schemaLocation="http://www.openarchives.org/LIBRARY/2.0/ http://www.openarchives.org/LIBRARY/2.0/LIBRARY-PHM.xsd">
    <repository>Test</repository>
    <records>
        <record>
            <ejemplar>
                <library_book:book
                        xmlns:library_book="http://www.w3c.es/LIBRARY/book/"
                        xmlns:book="http://www.w3c.es/LIBRARY/book/"
                        xmlns:bookAssets="http://www.w3c.es/LIBRARY/book/"
                        xmlns:bookAsset="http://www.w3c.es/LIBRARY/book/"
                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:schemaLocation="http://www.w3c.es/LIBRARY/book/ http://www.w3c.es/LIBRARY/replacement/book.xsd">
                    <book:bookAssets count="1">
                        <book:bookAsset nasset="1">
                            <book:bookAsset.id>value1</book:bookAsset.id>
                            <book:bookAsset.event>
                                <book:bookAsset.event.id>value2</book:bookAsset.event.id>
                            </book:bookAsset.event>
                        </book:bookAsset>
                    </book:bookAssets>
                </library_book:book>
            </ejemplar>
        </record>
    </records>
</REPOSITORY>

我想要访问value1value2价值观。为此,我试试这个:

// Standard of reading a XML file
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder;
Document doc = null;
XPathExpression expr = null;
builder = factory.newDocumentBuilder();
doc = builder.parse("MyXML.xml");

// Create a XPathFactory
XPathFactory xFactory = XPathFactory.newInstance();

// Create a XPath object
XPath xpath = xFactory.newXPath();

expr = xpath.compile("//REPOSITORY/records/record/ejemplar/library_book:book//book:bookAsset.event.id/text()");

Object result = expr.evaluate(doc, XPathConstants.STRING);

System.out.println("RESULT=" + (String)result);

但我没有得到任何结果。仅打印RESULT=

¿ 如何访问value1value2取值?¿ 要应用的 XPath 过滤器是什么?

提前致谢。

我正在使用JDK6。

4

3 回答 3

1

您在命名空间方面遇到问题,您可以做的是

  1. 考虑到他们
  2. local-name()使用 XPath函数忽略它们

解决方案 1 意味着实现一个NamespaceContext映射命名空间名称和 URI 的方法,并XPath在查询之前将其设置在对象上。

解决方案 2 很简单,您只需要更改您的 XPath(但根据您的 XML,您可以微调您的 XPath 以确保选择正确的元素):

XPath xpath = xFactory.newXPath();
expr = xpath.compile("//*[local-name()='bookAsset.event.id']/text()");
Object result = expr.evaluate(doc, XPathConstants.STRING);
System.out.println("RESULT=" + result);

ideone 上的可运​​行示例

您可以查看以下博客文章,以更好地了解 Java 中命名空间和 XPath 的使用(即使是旧的)

于 2012-11-13T08:10:21.957 回答
0

尝试

Object result = expr.evaluate(doc, XPathConstants.NODESET);

    // Cast the result to a DOM NodeList
    NodeList nodes = (NodeList) result;
    for (int i=0; i<nodes.getLength();i++){
      System.out.println(nodes.item(i).getNodeValue());
    }
于 2012-11-13T08:06:47.760 回答
0

一种方法是实现名称空间上下文,例如:

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;
    }

}

然后像这样使用它

        xpath.setNamespaceContext(new UniversalNamespaceResolver(doc));

您还需要将所有命名空间声明上移到根节点 (REPOSITORY)。否则,如果您有两个不同级别的命名空间声明,则可能会出现问题。

于 2012-11-13T08:59:29.607 回答