Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Construct XML with dynamic label and attributes in Scala?

Tags:

xml

scala

I want to be able to do this:

val myXml = <myTag { someAttributes }> </myTag> 

(because I don't know what the attribute details are at compile time)

and this:

val myXml = <{someTag}></{someTag}> 

This isn't valid Scala syntax. The closest I can come is using the Elem object to construct elements, but it's being a little troublesome (inserting PCDATA where I don't want it to). Is there any way of doing it like the above?

like image 518
Joe Avatar asked Oct 21 '09 13:10

Joe


2 Answers

val myXml = <myTag/> % Attribute(None, "name", Text("value"), Null) 

See scala.xml.Attribute for different constructors.

Adding the same attribute to all children:

scala> val xml = <root><a/><b/><c/></root> xml: scala.xml.Elem = <root><a></a><b></b><c></c></root>  scala> xml.child map (_ match {      | case elem : Elem => elem % Attribute(None, "name", Text("value"), Null)      | case x => x      | }) res3: Sequence[scala.xml.Node] = ArrayBuffer(<a name="value"></a>, <b name="value"></b>, <c name="value"></c>) 

You can also use the stuff in scala.xml.transform to do so recursively to all XML:

val rr = new RewriteRule {   override def transform(n: Node): Seq[Node] = n match {     case elem : Elem => elem % Attribute(None, "name", Text("value"), Null) toSeq     case other => other   } }  val rt = new RuleTransformer(rr)  scala> rt(xml) res5: scala.xml.Node = <root name="value"><a name="value"></a><b name="value"></b><c name="value"></c></root> 

Or you can add attributes to arbitrary parts of the xml:

scala> val xml = <root>{<a/> % Attribute(None, "name", Text("value"), Null)}</root> xml: scala.xml.Elem = <root><a name="value"></a></root> 

EDIT

Changing the name is easy to do on Scala 2.8, like this:

val someTag = "tag" val myXml = <root>{<a/>.copy(label = someTag)}</root> 
like image 178
Daniel C. Sobral Avatar answered Oct 20 '22 01:10

Daniel C. Sobral


Note: you need to

import scala.xml.Null 

to get this to work, and not scala.Null, which also exists.

like image 25
Henry Story Avatar answered Oct 20 '22 01:10

Henry Story