logo      
Custom Search

Re: Extracting attributes from XML...

Date: December 28, 2006
From: "Burak Emir" <burak.emir@xxxxxxxxx>

In-reply-to: <45940F56.7000105@xxxxxxxxxxxxxx>
References: <45940F56.7000105@xxxxxxxxxxxxxx>

Hi Andy,

On 12/28/06, Andy Dwelly <andy.dwelly@xxxxxxxxxxxxxx> wrote:
I have some xml:

<?xml version = "1.0" ?>
<marius title="This is a test">
  <narrative>now is the time for all good men to come to the aid of the
party.</narrative>
</marius>


beware that you might end up with several children of node "marius"... I noticed that the "preserve whitespace = false" option of the constructingparser seems to be buggy, so I use preserve whitespace = true.


...and I have some a method in an object to process it:

def process() = {
      val src = "">      val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false)
      val doc = cpa.document()
      val model = new Model();

      doc.docElem match {
        case Elem(_, "marius", attributes, _, _) => model.title =
attributes.get("title")
        case _ => {}
      }
      model
    }

where Model has a variable title: String.

The compiler complains

found   : scala.Option[scala.Seq[scala.xml.Node]]
required: java.lang.String
        case Elem(_, "marius", attributes, _, _) => model.title =
attributes.get
("title")

^
one error found

...not unreasonably, scala.Option[scala.Seq[scala.xml.Node]] is actually
how XML attributes appear to be defined in Elem. How do I actually get
at the text of the title attribute, e.g. "This is a test" ? I suppose a

the following all work, but require that you have an import xml.NodeSeq in scope. The last option will assign the empty string if there is no attribute "title", whereas the first three will all blow up with an exception. Here, the text method return something quite close to the XPath text() function.

node match {
        case n @ Elem(_, "marius", attributes, _, _) =>
          //val z:String = attributes.get("title") match {
          //  case Some(v) => v.text
          //}

          //val z:String = attributes.get("title").get.text

          //val z:String = attributes("title").text

          val z:String = (node \ "@title").text
          Console.println(z)
      }


supplementary question is should I really be starting from doc.docElem
as the root node ?

yes, that's the right node. since the xml spec permits procinstrs and comments before the actual node.

But as I said above, beware that if your node ends up with more than one child (due to the parser not weeding out whitespace nodes), then the pattern won't match, as it will have more than one child.

hope this helps,
Burak


--
Burak Emir
Research Assistant / PhD Candidate
Programming Methods Group
EPFL, 1015 Lausanne, Switzerland
http://lamp.epfl.ch/~emir


Custom Search
home | non blog view