在Scala中执行复杂的XPath查询

在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不支持generics,因此在Scala中使用会很痛苦。 (Java的其他XML库在Java中往往更加痛苦,但我承认我不了解真实情况。)

 //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]) ) 

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

但是我无法回答关于命名空间的问题。 如果可能的话,不知道如何在搜索中使用它们。 文档提到@{uri}attribute作为前缀属性,并没有提到有关前缀元素的任何内容。 另请注意,您需要传递一个解析为所需命名空间的URI,因为不支持搜索中的文字命名空间。

我想我会选择轻松拉皮条的XOM 。 XOM作者决定不公开子节点集合等等,这有点令人遗憾,但是他们在Java中比在Scala中做更多的工作和更少的优势。 (它是一个设计良好的图书馆。)

编辑:毕竟我最终拉断了JDOM,因为XOM没有提前编译XPath查询。 由于这次我的大部分努力都是针对XPath的,所以我能够找到一个能够回避大多数generics问题的好模型。 在org.jdom.Element中提出方法getChildrengetAttributes以及getAdditionalNamespaces合理泛化版本应该不会太难(通过使用稍微更改名称的新方法对库进行getAdditionalNamespaces )。我不认为有一个修复getContent ,我不确定getDescendants

Scales Xml添加了基于字符串的完整XPath评估和内部DSL,为查询提供了相当完整的覆盖

我想当scalaxmljaxen成熟时,我们将能够在scala的内置XML类中可靠地执行此操作。

我建议使用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))