Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An example of xml processing but using anti-xml instead of Scala xml

Tags:

scala

anti-xml

I'd like to see a rewrite of bellow script using http://anti-xml.org instead of Scala XML.

This is an excerpt from Chapter 10. Herding XML in Scala - http://ofps.oreilly.com/titles/9780596155957/HerdingXMLInScalaDSLs.html

// code-examples/XML/reading/pattern-matching-script.scala
import scala.xml._
val someXML =
 <sammich>
   <bread>wheat</bread>
   <meat>salami</meat>
   <condiments>
     <condiment expired="true">mayo</condiment>
     <condiment expired="false">mustard</condiment>
   </condiments>
</sammich>

someXML match {
 case <sammich>{ingredients @ _*}</sammich> => {
    for (cond @ <condiments>{_*}</condiments> <- ingredients)
      println("condiments: " + cond.text)
    }
}

Thanks

like image 869
Rodolfo Avatar asked Aug 05 '11 19:08

Rodolfo


1 Answers

I'm not familiar with antixml, however, as there is no other answer, I'll make a try

Just for the record, your code returns

  mayo
  mustard

More precisely, the string starts with the blanks/newline between the end of and the start of the first . The blanks between mayo and mustard are the ones between the two condiment, and the blanks after mustard is the one before the closing .

In antixml, first thing to do seems to convert your, which is simply

val someAntiXml = someXML.anti

Getting the condiments part is easy :

var condiments = someAntiXml \ 'condiments

Then one has to extract the text. It sounded like the way to do this was

condiments \\ text

But \\ does not traverse the structure in order, it looks like breadth-first traversal. As a consequence, the blanks, which are just under condiments, comes before mayo and mustard, which are one level below, in the elements.

So here is a possible implementation to retrieve the text. Maybe there is a more standard way, but I did not find one.

def textOf(g: Group[Node]) : String = 
  g.toList.map{
    case Elem(_, _, _, _, children) => textOf(children) 
    case t: Text => t.text
    case c: CDATA => c.text 
    case _ => ""
  }.mkString

Then textOf(someAntiXml \ "condiments") gives the expected result.

like image 166
Didier Dupont Avatar answered Nov 12 '22 18:11

Didier Dupont