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
def nodeHasValue(node:Node,value:String) = node.attributes.value != null && node.attributes.value.contains(value)
(x \\ "_").filter( nodeHasValue(_,"test"))
Code snippet in the question doesn't working with Scala 2.8 - due to this comparasion
(_ == value)
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)
.
First, XML are literals in Scala, so:
val xml = <div><span class="test">hello</span><div class="test"><p>hello</p></div></div>
Now, as to the problem:
def attributeValueEquals(value: String)(node: Node) = {
node.attributes.exists(_.value.text == value)
}
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
":
val testResults = xml \\ "_" filter attributeValueEquals("test")
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:
def getByAtt(e: Elem, att: String, value: String) = {
def filterAtribute(node: Node, att: String, value: String) = (node \ ("@" + att)).text == value
e \\ "_" filter { n=> filterAtribute(n, att, value)}
}
And then
getByAtt(xml, "class", "test")
This will differentiate between class="test"
and "notclass="test"
I'm quite new to Scala, I propose you this solution, but I'm not sure this is the best one:
def attributeValueEquals(value: String)(node: Node) = {
node.attributes.foldLeft(false)((a : Boolean, x : MetaData) => a | (x.value == value))
}
val testResults = (xml \\ "_").filter(attributeValueEquals("test"))
println("testResults: " + testResults )
// prints: testResults: ArrayBuffer(<span class="test">hello</span>,
// <div id="test"><p>hello</p></div>,
// <random any="test"></random>)