- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
XML hell
Tue, 2009-10-27, 03:05
I'm hoping this is just me being dumb, but I'm desperate for help.
Basically I want to perform some modification to some existing XML. So
far everything I've come across seems fairly painful (or at least
excessively long).
eg
http://stackoverflow.com/questions/970675/scala-modifying-nested-element...
http://stackoverflow.com/questions/1582244/how-to-access-parent-element-...
I was very much hoping for something similar to (the brilliant!)
elementTree API on Python... and extract out lists/arrays of Nodes,
manipulate and regenerate the XML from that.
But it looks like everything boils down to matchers.
What would be the suggested way to add an extra node to the below?
foo1
foo2
foo3
?
Any comments highly appreciated
Ken
Tue, 2009-10-27, 14:47
#2
Re: XML hell
2009/10/27 Ken Faulkner :
> [...]
> Basically I want to perform some modification to some existing XML. So far
> everything I've come across seems fairly painful (or at least excessively
> long).
> [...]
Hello,
it would indeed be nice to have a mutable XML representation in Scala,
which could facilitate this kind of manipulation. Using the tools in
the Scala standard library, the simplest approach that comes to my
mind is to do pattern matching but delegate some of the necessary work
to the scala.xml.transform framework:
import scala.xml._
import scala.xml.transform._
val xexpr =
foo1
foo2
foo3
val addFoo = new RuleTransformer(new RewriteRule {
override def transform(node: Node) = node match {
case {foos @ _*} =>
{foos ++ another foo }
case node =>
super.transform(node)
}
})
print(addFoo(xexpr))
Ciao,
Thomas
Tue, 2009-10-27, 14:57
#3
Re: XML hell
I was trying to do some of the sameyesterday (filtering some tags) and so
your issue was relevant to me. For your case I came up with the following
solution:
import scala.xml._
val x =
foo1
foo2
foo3
def addFoos(doc:Node, foos:Seq[Node]) : Node = {
doc match {
case {ff @ _*} => {ff ++ foos}
case Elem(prefix, label, attribs, scope, children @ _*) => Elem(prefix,
label, attribs, scope, children map (addFoos(_, foos)):_*)
case other => other
}
}
println(addFoos(x, foo4 foo5))
println(addFoos(x, foo6 ))
It took me a little bit of time to figure out the recursion, but I think the
end result is in fact pretty simple.
ken.faulkner@gmail.com wrote:
>
> I'm hoping this is just me being dumb, but I'm desperate for help.
>
> Basically I want to perform some modification to some existing XML. So
> far everything I've come across seems fairly painful (or at least
> excessively long).
>
>
> eg
>
> http://stackoverflow.com/questions/970675/scala-modifying-nested-element...
>
> http://stackoverflow.com/questions/1582244/how-to-access-parent-element-...
>
> [...]
>
> Ken
>
Tue, 2009-10-27, 15:07
#4
Re: XML hell
Given my transform definition above, this seems simpler to me. No recursion required:
transform(xml) {case <foos>{f @ _*}</foos> => <foos>{f ++ <foo name = "10">whatever</foo>}</foos>}
Bill
On Tue, Oct 27, 2009 at 3:45 PM, huynhjl <jlh276-gh@yahoo.com> wrote:
transform(xml) {case <foos>{f @ _*}</foos> => <foos>{f ++ <foo name = "10">whatever</foo>}</foos>}
Bill
On Tue, Oct 27, 2009 at 3:45 PM, huynhjl <jlh276-gh@yahoo.com> wrote:
I was trying to do some of the sameyesterday (filtering some tags) and so
your issue was relevant to me. For your case I came up with the following
solution:
import scala.xml._
val x = <bar>
<foos>
<foo name = "1"> foo1 </foo>
<foo name = "2"> foo2 </foo>
<foo name = "3"> foo3 </foo>
</foos>
</bar>
def addFoos(doc:Node, foos:Seq[Node]) : Node = {
doc match {
case <foos>{ff @ _*}</foos> => <foos> {ff ++ foos} </foos>
case Elem(prefix, label, attribs, scope, children @ _*) => Elem(prefix,
label, attribs, scope, children map (addFoos(_, foos)):_*)
case other => other
}
}
println(addFoos(x, <foo name = "4"> foo4 </foo><foo name="5">foo5</foo>))
println(addFoos(x, <foo name = "6"> foo6 </foo>))
It took me a little bit of time to figure out the recursion, but I think the
end result is in fact pretty simple.
ken.faulkner@gmail.com wrote:
>
> I'm hoping this is just me being dumb, but I'm desperate for help.
>
> Basically I want to perform some modification to some existing XML. So
> far everything I've come across seems fairly painful (or at least
> excessively long).
>
>
> eg
>
> http://stackoverflow.com/questions/970675/scala-modifying-nested-elements-in-xml
>
> http://stackoverflow.com/questions/1582244/how-to-access-parent-element-in-scala-xml
>
> [...]
>
> Ken
>
--
View this message in context: http://www.nabble.com/-scala--XML-hell-tp26071020p26077986.html
Sent from the Scala mailing list archive at Nabble.com.
Tue, 2009-10-27, 22:37
#5
Re: XML hell
Thanks for the suggestions/code everyone.
This will definitely put me on the right track. Although I still have to admit longing for a more simple API:
val start = XML.load(...)
val mutable = start.toMutable
mutable \ "foos" += <foo name="4">foo4</foo>
val end = mutable.toImmutable
(as Marcus mentioned earlier).
Still, I'll use what I've got now...
cheers,
Ken
On 28/10/2009, at 12:48 AM, Bill Burdick wrote:
This will definitely put me on the right track. Although I still have to admit longing for a more simple API:
val start = XML.load(...)
val mutable = start.toMutable
mutable \ "foos" += <foo name="4">foo4</foo>
val end = mutable.toImmutable
(as Marcus mentioned earlier).
Still, I'll use what I've got now...
cheers,
Ken
On 28/10/2009, at 12:48 AM, Bill Burdick wrote:
Given my transform definition above, this seems simpler to me. No recursion required:
transform(xml) {case <foos>{f @ _*}</foos> => <foos>{f ++ <foo name = "10">whatever</foo>}</foos>}
Bill
On Tue, Oct 27, 2009 at 3:45 PM, huynhjl <jlh276-gh@yahoo.com> wrote:
I was trying to do some of the sameyesterday (filtering some tags) and so
your issue was relevant to me. For your case I came up with the following
solution:
import scala.xml._
val x = <bar>
<foos>
<foo name = "1"> foo1 </foo>
<foo name = "2"> foo2 </foo>
<foo name = "3"> foo3 </foo>
</foos>
</bar>
def addFoos(doc:Node, foos:Seq[Node]) : Node = {
doc match {
case <foos>{ff @ _*}</foos> => <foos> {ff ++ foos} </foos>
case Elem(prefix, label, attribs, scope, children @ _*) => Elem(prefix,
label, attribs, scope, children map (addFoos(_, foos)):_*)
case other => other
}
}
println(addFoos(x, <foo name = "4"> foo4 </foo><foo name="5">foo5</foo>))
println(addFoos(x, <foo name = "6"> foo6 </foo>))
It took me a little bit of time to figure out the recursion, but I think the
end result is in fact pretty simple.
ken.faulkner@gmail.com wrote:
>
> I'm hoping this is just me being dumb, but I'm desperate for help.
>
> Basically I want to perform some modification to some existing XML. So
> far everything I've come across seems fairly painful (or at least
> excessively long).
>
>
> eg
>
> http://stackoverflow.com/questions/970675/scala-modifying-nested-elements-in-xml
>
> http://stackoverflow.com/questions/1582244/how-to-access-parent-element-in-scala-xml
>
> [...]
>
> Ken
>
--
View this message in context: http://www.nabble.com/-scala--XML-hell-tp26071020p26077986.html
Sent from the Scala mailing list archive at Nabble.com.
I do this all the time in my Java code (using XOM), and its absense from
Scala is an obstacle - and as you say, the methods presented all look pretty
painful. Of course, you could just use something like XOM instead of
scala.xml, but I can see why that's an ugly choice.
I agree with the decision to make scala.xml's nodes immutable, but I've
argued the need before for a mutable version of them. The process would be
to transform one immutable structure into another via a short-lived mutable
copy.
val start = XML.load(...)
val mutable = start.toMutable
mutable \ "foos" += foo4
val end = mutable.toImmutable
Fundamentally this isn't too different from the approaches presented
elsewhere: filter the original xml to produce a new copy based on a set of
criteria, replacing only those elements that have changed. The difference is
in how the criteria are built.
Sadly my functional fu is too weak to write this myself, but I believe it
could be achieved. I've added a request on UserVoice, hopefully somebody can
pick it up. Go vote for it!
http://scala.uservoice.com/pages/30665-libraries/suggestions/366249-scal...
ken.faulkner@gmail.com wrote:
>
> I'm hoping this is just me being dumb, but I'm desperate for help.
>
> Basically I want to perform some modification to some existing XML. So
> far everything I've come across seems fairly painful (or at least
> excessively long).
>
>
> eg
>
> http://stackoverflow.com/questions/970675/scala-modifying-nested-element...
>
> http://stackoverflow.com/questions/1582244/how-to-access-parent-element-...
>
>
>
> I was very much hoping for something similar to (the brilliant!)
> elementTree API on Python... and extract out lists/arrays of Nodes,
> manipulate and regenerate the XML from that.
> But it looks like everything boils down to matchers.
>
> What would be the suggested way to add an extra node to the below?
>
>
>
>
>
> foo1
> foo2
> foo3
>
>
>
>
>
> ?
>
> Any comments highly appreciated
>
> Ken
>
>
>