如何使用XPath在Java中使用名称空间查询XML?

问题描述 投票:61回答:8

当我的XML看起来像这样(没有xmlns)时,我可以像/workbook/sheets/sheet[1]一样轻松地使用XPath查询它>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook>
  <sheets>
    <sheet name="Sheet1" sheetId="1" r:id="rId1"/>
  </sheets>
</workbook>

但是当看起来像这样我就不能

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
  <sheets>
    <sheet name="Sheet1" sheetId="1" r:id="rId1"/>
  </sheets>
</workbook>

有什么想法吗?

[当我的XML看起来像这样(没有xmlns)时,我可以使用XPath像/ workbook / sheets / sheet [1]轻松查询它[1] [[[[]]]

java xml xpath xml-namespaces
8个回答
66
投票
在第二个示例XML文件中,元素绑定到名称空间。您的XPath尝试处理绑定到默认“无名称空间”名称空间的元素,因此它们不匹配。

首选方法是使用名称空间前缀注册名称空间。它使您的XPath更加易于开发,阅读和维护。

但是,不是强制性的,您必须注册名称空间并在XPath中使用名称空间前缀。


57
投票
您的问题是默认名称空间。查看本文,了解如何在XPath中处理名称空间:http://www.edankert.com/defaultnamespaces.html

他们得出的结论之一是:


37
投票
您要在源XML中选择的所有名称空间必须与主机语言中的前缀相关联。在Java / JAXP中,这是通过使用javax.xml.namespace.NamespaceContext实例为每个名称空间前缀指定URI来完成的。不幸的是,SDK中提供了[NamespaceContext

无实现


4
投票
如果使用的是Spring,它已经包含org.springframework.util.xml.SimpleNamespaceContext。

import org.springframework.util.xml.SimpleNamespaceContext; ... XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); SimpleNamespaceContext nsc = new SimpleNamespaceContext(); nsc.bindNamespaceUri("a", "http://some.namespace.com/nsContext"); xpath.setNamespaceContext(nsc); XPathExpression xpathExpr = xpath.compile("//a:first/a:second"); String result = (String) xpathExpr.evaluate(object, XPathConstants.STRING);


1
投票
确保您在XSLT中引用名称空间

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" >


1
投票
我编写了一个简单的NamespaceContext实现(here),它以Map<String, String>作为输入,其中key是前缀,value是命名空间。

NamespaceContext特殊化之后,您可以在unit tests中看到它的工作方式。


0
投票
令人惊讶的是,如果我没有设置factory.setNamespaceAware(true);,那么您提到的xpath可以在使用和不使用名称空间的情况下使用。您只是不能选择“指定了名称空间”的东西,而只能选择通用xpath。去搞清楚。因此,这可能是一个选择:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false);


0
投票
要添加到现有答案中的两件事:

  • 我不知道您是否在问以下问题:如果您不使用文档构建器工厂上的setNamespaceAware(true),[X0]您的XPath实际上适用于第二个文档(false是默认设置)。
© www.soinside.com 2019 - 2024. All rights reserved.