我尝试使用scala运行XPath查询,但它似乎无法正常工作。 我的Xml看起来像(简化):
<application>
<process type="output" size ="23">
<channel offset="0"/>
....
<channel offset="4"/>
</process>
<process type="input" size ="16">
<channel offset="20"/>
....
<channel offset="24"/>
</process>
</application>
我想要使用process
属性检索input
,为此我使用此XPath查询:
//process[@type='input']
这应该有用,我用xpathtester验证了 现在,我的scala代码如下所示:
import scala.xml._
val x = XML.loadFile("file.xml")
val process = (x \\ "process[@type='input']") // will return empty NodeSeq() !!!
process
结束为空,它无法捕获我想要的内容。我像这样工作:
val process = (x \\ "process" filter( _ \"@type" contains Text("input")))
这更加丑陋。我的原始查询不应该起作用的任何已知原因?
答案 0 :(得分:4)
“XPath”不应用于描述Scala标准库支持的内容。 XPath是一种成熟的表达式语言,迄今为止已有两个最终版本和第三个版本:
充其量你可以说Scala只有一小部分受XPath启发的操作。所以你不能指望采用XPath表达式并直接将它们粘贴到Scala而不需要做更多的工作。
第三方库可以为您提供更好的实际XPath表达式支持,包括:
答案 1 :(得分:1)
这样做的一种方法是使用kantan.xpath:
import kantan.xpath._
import kantan.xpath.implicits._
val input = """
| <application>
| <process type="output" size ="23">
| <channel offset="0"/>
| <channel offset="4"/>
| </process>
| <process type="input" size ="16">
| <channel offset="20"/>
| <channel offset="24"/>
| </process>
| </application>
| """.stripMargin
val inputs = input.evalXPath[List[Node]](xp"//process[@type='input']")
这会产生List[Node]
,但您可以检索更有趣类型的值 - 通道偏移列表,例如:
input.evalXPath[List[Int]](xp"//process[@type='input']/channel/@offset")
// This yields Success(List(20, 24))
答案 2 :(得分:0)
我相信scala xml实现无法处理这种复杂的XPath查询。然而,创建一个小的丰富包装器来减少混乱并不困难,例如看看this thread。使用建议的包装器,您可以像这样解决问题:
x \\ "process" \@ ("type", _ == "input")