I saw the following example on Nabble, where the goal was to return all nodes that contain an attribute with an id of X that contains a value 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 )
As an extension to this how would one do the following: Find all nodes that contain any attribute that contains a value of 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"/> )
I was thinking I could use a _ like so:
val testResults = (xml \\ "_").filter(attributeEquals("_","test"))
But it doesn't work. I know I can use pattern matching, but just wanted to see if I could do some magic with the filtering.
Cheers - Ed
Code snippet in the question doesn't working with Scala 2.8 - due to this comparasion
Needs to be replaced with(_.text == value)
or(_ == Text(value))
or change type of value from String to Text.And in Daniel's answer
(_.value == value)
needs to be replaced with(_.value.text == value)
.I'm quite new to Scala, I propose you this solution, but I'm not sure this is the best one:
First, XML are literals in Scala, so:
Now, as to the problem:
In fact, I'd have used "
exists
" instead of "filter
" and "defined
" for the original problem as well.Finally, I personally prefer operator style syntax, particularly when you have a ready function, instead of an anonymous one, to pass to "
filter
":The original mixes operator style for "
\\
" and dot style for "filter
", which ends up quite ugly.The previous solutions didn't work for me because they all look for any value that matches. If you want to look for a particular attribute with a value, here is my solution:
And then
This will differentiate between
class="test"
and"notclass="test"