在 Scala 中执行复杂的 XPath 查询

2022-09-04 20:00:51

在 scala 中用于对文档执行以下 XPath 查询的最简单 API 是什么?

//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())]

//s:Annotation[s:Content/s:Parameter[@role='id' and not(text())]]/@type

(s定义为特定命名空间的昵称)

我能找到的关于 Scala 的 XML 库的唯一文档没有关于执行复杂的实际 XPath 查询的信息。

我曾经喜欢JDOM用于此目的(在Java中),但是由于JDOM不支持泛型,因此在Scala中使用会很痛苦。(其他用于Java的XML库在Java中往往更加痛苦,但我承认我并不真正了解这个领域。


答案 1
//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())]

好吧,我不明白符号,在XPath规范上也找不到它。但是,忽略这看起来像这样:s:

(
  (xml 
    \\ "Annotation" 
    filter (_ \ "@type" contains Text("x"))
  ) 
  \ "Content" 
  \ "Parameter" 
  filter (el => (el \ "@type" contains Text("type")) && el.isInstanceOf[Text])
)

请注意括号的必要性,因为 over 的优先级更高。我已将格式更改为多行表达式,因为Scala等效项对于单行来说太冗长了。\filter

但是,我无法回答命名空间。没有线索如何与他们一起搜索,如果可能的话。文档提到了前缀属性,没有提到任何关于前缀元素的内容。另外,请注意,您需要传递一个解析为所需命名空间的 uri,因为不支持搜索中的文字命名空间。@{uri}attribute


答案 2

我想我会和轻度拉皮条的XOM一起去。有点可惜XOM的作者决定不公开子节点等的集合,但他们在Java中这样做比在Scala中有更多的工作和更少的优势。(它是一个设计精良的库。

编辑:毕竟,我最终拉皮条了JDOM,因为XOM不会提前编译XPath查询。由于这次我的大部分精力都集中在XPath上,所以我能够提出一个很好的模型来回避大多数泛型问题。提出方法和 in 的合理泛型化版本应该不会太难(通过使用名称稍有变化的新方法拉皮条库)。我不认为有修复方法,我不确定.getChildrengetAttributesgetAdditionalNamespacesorg.jdom.ElementgetContentgetDescendants


推荐