使用scala查找具有与特定值匹配的属性的所有节点

ed.*_*ed. 11 xml parsing scala

我在Nabble上看到了以下示例,其目标是返回包含属性为X且包含值Y的属性的所有节点:

//find all nodes with an attribute "class" that contains the value "test"
val xml = XML.loadString( """<div>
<span class="test">hello</span>
<div class="test"><p>hello</p></div>
</div>""" )

def attributeEquals(name: String, value: String)(node: Node) = 
{ 
    node.attribute(name).filter(_==value).isDefined
}

val testResults = (xml \\ "_").filter(attributeEquals("class","test")) 
//prints: ArrayBuffer(
//<span class="test">hello</span>, 
//<div class="test"><p>hello</p></div>
//) 
println("testResults: " + testResults ) 
Run Code Online (Sandbox Code Playgroud)

作为对此的扩展,将如何执行以下操作:查找包含任何包含值Y的属性的所有节点:

//find all nodes with any attribute that contains the value "test"
val xml = XML.loadString( """<div>
 <span class="test">hello</span>
 <div id="test"><p>hello</p></div>
 <random any="test"/></div>""" )
 //should return: ArrayBuffer(
 //<span class="test">hello</span>, 
 //<div id="test"><p>hello</p></div>, 
 //<random any="test"/> )
Run Code Online (Sandbox Code Playgroud)

我以为我可以使用_像这样:

val testResults = (xml \\ "_").filter(attributeEquals("_","test")) 
Run Code Online (Sandbox Code Playgroud)

但它不起作用.我知道我可以使用模式匹配,但只是想看看我是否可以通过过滤做一些魔术.

干杯 - 艾德

Dan*_*ral 18

首先,XML是Scala中的文字,因此:

val xml = <div><span class="test">hello</span><div class="test"><p>hello</p></div></div>
Run Code Online (Sandbox Code Playgroud)

现在,至于问题:

def attributeValueEquals(value: String)(node: Node) = {
     node.attributes.exists(_.value.text == value)
}
Run Code Online (Sandbox Code Playgroud)

事实上,我也使用" exists"而不是" filter"和" defined"作为原始问题.

最后,我个人更喜欢操作符样式语法,特别是当你有一个准备好的函数而不是匿名函数时,传递给" filter":

val testResults = xml \\ "_" filter attributeValueEquals("test")
Run Code Online (Sandbox Code Playgroud)

原版混合了" \\"的操作符样式和" "的点样式filter,最终非常难看.