2011-09-27 16 views
5

¿Alguna manera de simplificar lo siguiente? o reducir el código repetitivo con otra función?Scala XML, Obtener nodos donde el padre tiene un valor de atributo coincidente

scala> val ns = <foo><bar id="1"><tag>one</tag><tag>uno</tag></bar><bar id="2"><tag>two</tag><tag>dos</tag></bar></foo> 
ns: scala.xml.Elem = <foo><bar id="1"><tag>one</tag><tag>uno</tag></bar><bar id="2"><tag>two</tag><tag>dos</tag></bar></foo> 

scala> (ns \\ "bar" filterNot{_ \\ "@id" find { _.text == "1" } isEmpty}) \\ "tag" 
res0: scala.xml.NodeSeq = NodeSeq(<tag>one</tag>, <tag>uno</tag>) 

Respuesta

15

sólo pude encontrar una mejora menor, la prueba find/isEmpty se puede sustituir por exists:

(ns \\ "bar" filter { _ \\ "@id" exists (_.text == "1") }) \\ "tag" 

Editar después de aclarar comentario:

Esa es una muy buena idea! Pruebe esto para el tamaño:

import xml._ 

implicit def richNodeSeq(ns: NodeSeq) = new { 

    def \@(attribMatch: (String, String => Boolean)): NodeSeq = 
    ns filter { _ \\ ("@" + attribMatch._1) exists (s => attribMatch._2(s.text)) } 

} 

ns \\ "bar" \@ ("id", _ == "1") \\ "tag" 

He usado un predicado en lugar de codificar la comparación del valor del atributo.

+1

Gracias por la mejora. Lo que realmente estoy buscando es una forma de crear un selector para el filtro {_ \\ "@id" existe (_.text == "1")}) luego se ve algo así como (x \\ "bar" \ @ ("@id", "1") \\ "tag" – eptx

+0

Me gusta tu idea. He editado mi respuesta con una posible solución. – Lachlan

Cuestiones relacionadas