为什么 Java 的 XPath 求值器需要 NamespaceContext 和前缀来查询 OpenXML 文件?

问题描述 投票:0回答:1

我正在尝试了解 XPath 评估如何适用于 OpenXML 文件,特别是以下代码片段中的 Excel(为简洁起见,我删除了不相关的节点):

<?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"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="x15 xr xr6 xr10 xr2"
    xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
    xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision"
    xmlns:xr6="http://schemas.microsoft.com/office/spreadsheetml/2016/revision6"
    xmlns:xr10="http://schemas.microsoft.com/office/spreadsheetml/2016/revision10"
    xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2">
    <!-- [..] -->
    <sheets>
        <sheet name="Sheet-One" sheetId="1" r:id="rId1" />
        <sheet name="Sheet-Two" sheetId="3" r:id="rId2" />
        <sheet name="Sheet-Three" sheetId="4" r:id="rId3" />        
    </sheets>
    <!-- [..] -->
</workbook>

当我使用不带

NamespeceContext
(且禁用行
xp.namespaceContext = nc
)的 XPath 查询此 XML 时,它找不到节点,即使 XPath-Tester 找到了。

//val xpath = "/workbook/sheets/sheet" // <-- doesn't work
val xpath = "/xx:workbook/xx:sheets/xx:sheet"
val xp = XPathFactory.newInstance().newXPath()
val nc = NamespaceContextImpl()
nc.addNamespace("xx", "http://schemas.openxmlformats.org/spreadsheetml/2006/main")
xp.namespaceContext = nc
val sheetNodes = xp.compile(xpath).evaluate(document, XPathConstants.NODESET) as NodeList

我有一个理论,但我无法确认,这是因为

workbook
元素指定没有前缀的
xmlns
命名空间,因此它会自动应用于所有其他节点。但是,XPath 中所需的 free 前缀
xx
(或其他任何内容)是怎么回事?人们如何弄清楚这一点?如果我没有找到
NamespaceContext
here我永远不会想出这个。这些技巧从哪里学来的?

java excel kotlin xpath openxml
1个回答
0
投票

你的问题读起来更像是沮丧的呼喊,而不是请求可以得到事实答案的信息。

回应沮丧的呼声,毫无疑问,XPath 中处理名称空间的方式已被证明对许多用户来说是一个很大的可用性问题。不幸的是,虽然每个人都知道这一点,但这是一种随后很难纠正的设计错误。后来的 XPath 版本试图缓解这一问题,但遗憾的是,许多流行的 XPath 库(包括 JDK 默认附带的库)从未实现过 XPath 1.0 之外的任何内容。

大多数语言都有这样的可用性陷阱,你可以从经验中学习。当我处理一项新技术时,我自己的学习风格通常是浏览一本有关该主题的书,一本好的教科书通常会给出足够的警告,帮助你避免此类陷阱。然而,如今,我们中的许多人必须学习的新技术超出了书架上的空间,许多人通过反复试验以及复制和粘贴示例来学习。如果您的学习风格是通过反复试验来学习,那么恐怕您必须接受自己会犯错误,而且其中一些错误并不明显。

© www.soinside.com 2019 - 2024. All rights reserved.