在scala中使用哪种最简单的API来对文档执行以下XPath查询?
//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查询的信息。
我曾经为此目的(在Java中)喜欢JDOM,但由于JDOM不支持泛型,因此在Scala中使用会很痛苦。 (Java的其他XML库在Java中往往更加痛苦,但我承认我不了解真实情况。)
答案 0 :(得分:12)
//s:Annotation[@type='attitude']/s:Content/s:Parameter[@role='type' and not(text())]
好吧,我不理解s:
符号,也无法在XPath规范中找到它。但是,忽略这将是这样的:
(
(xml
\\ "Annotation"
filter (_ \ "@type" contains Text("x"))
)
\ "Content"
\ "Parameter"
filter (el => (el \ "@type" contains Text("type")) && el.isInstanceOf[Text])
)
请注意括号的必要性,因为\
优先于filter
。我已将格式更改为多行表达式,因为Scala等效对于单行来说太冗长了。
@{uri}attribute
作为前缀属性,并没有提到有关前缀元素的任何内容。另请注意,您需要传递一个解析为所需命名空间的URI,因为不支持搜索中的文字命名空间。
答案 1 :(得分:3)
我想我会轻易拉扯XOM。 XOM作者决定不暴露子节点集等等,这有点令人遗憾,但他们在Java中比在Scala中更多的工作和更少的优势。 (这是一个设计良好的图书馆。)
编辑:毕竟我最终花了大量的JDOM,因为XOM没有提前编译XPath查询。由于我的大部分努力都是针对XPath的,所以我能够提出一个很好的模型来回避大多数泛型问题。在getChildren
中提出方法getAttributes
和getAdditionalNamespaces
以及org.jdom.Element
的合理通用版本应该不会太难(通过使用新方法对库进行拉伸略有改变的名字。)我认为getContent
没有修复,我不确定getDescendants
。
答案 2 :(得分:3)
Scales Xml添加了基于字符串的完整XPath评估和内部DSL,为查询提供了相当完整的覆盖
答案 3 :(得分:1)
我想当scalaxmljaxen成熟时,我们将能够在scala的内置XML类中可靠地执行此操作。
答案 4 :(得分:0)
我建议使用kantan.xpath:
import kantan.xpath._
import kantan.xpath.implicits._
input.evalXPath[List[String]](xp"/annotation[@type='attitude']/content/parameter[@role='type' and not(text())]/@value")
这会产生:
res1: kantan.xpath.XPathResult[List[String]] = Success(List(foobar))