在Scala中执行复杂的XPath查询

时间:2010-06-16 19:01:57

标签: java xml scala xpath jdom

在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中往往更加痛苦,但我承认我不了解真实情况。)

5 个答案:

答案 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中提出方法getAttributesgetAdditionalNamespaces以及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))