从 XPath 表达式获取/列出前缀



我有一些XML(实际上是XBRL)文档,其中包含一些元素,其test属性包含XPath表达式:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<link:linkbase 
xmlns:ea="http://xbrl.org/2008/assertion/existence"
xmlns:generic="http://xbrl.org/2008/generic" 
xmlns:link="http://www.xbrl.org/2003/linkbase"
xmlns:xlink="http://www.w3.org/1999/xlink" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xff="http://www.xbrl.org/2010/function/formula">
<generic:link xlink:role="http://www.xbrl.org/2003/role/link" xlink:type="extended">
<!-- .... -->
<va:valueAssertion 
... some attribs ...
test="if(xff:has-fallback-value(xs:QName('someQName'))) then false() else (count($someVariable) ge 1)"
/>
<!-- ... -->
</generic:link>
</link:linkbase>

处理 XPath 表达式的约定是,它对前缀使用与 XML 文档中声明的相同的命名空间。

我们还有一些(自定义)linting 机制,其中包含一个规则,用于检查声明的前缀及其命名空间是否在文档中"使用"。

这意味着在上面的 xml 示例中,xff 和 xs 前缀应被识别为"used",因为它们存在于 XPath 表达式中。然而,标准工具(在 Java 中)并不能帮助我们看到这种情况。

例如,我可以在范围内获取所有前缀,并检查是否可以在 XPath 字符串中找到"前缀:";但这似乎是一个非常有缺陷的解决方案,并且容易出现误报和漏报。

另一种方法是使用命名空间绑定的所有可能组合"仅"计算 XPath 表达式,并检查最小命名空间集是什么。这也不会涵盖所有内容,因为评估可能会跳过整个代码分支。(例如,当遇到 if 语句时)。其次,可能性的爆炸式增长非常快,因为我们谈论的是许多(~100)包含多个XPath表达式的文档。

有谁知道解决这个问题的[n](好)方法?目前,我们在JVM上使用Scala来实现检查。因此,原生Java或Scala解决方案是首选。如果需要,其他JVM语言或依赖于非Java工具是可以接受的。

使用javax.xml.xpath.XPath#compile(String)解析文档中的所有 XPath 表达式。

要了解表达式中引用了哪些命名空间前缀,请准备一个NamespaceContext实现,该实现记录所请求命名空间绑定的前缀,并在调用 compile 方法之前通过XPath#setNamespaceContext(NamespaceContext)进行设置。

基于该前缀列表并给定包含表达式字符串的属性上的命名空间绑定,然后可以构建所有已使用命名空间的列表。

最新更新