tags:

views:

296

answers:

4

In Scala REPL:

val input = <outerTag xmlns="http://xyz"&gt; <innerTag> </innerTag> </outerTag>

input\\@"innerTag"

=>

<innerTag xmlns="http://xyz"&gt; </innerTag>

How do I stop Scala do this? Why can't it just give me <innerTag> </innerTag>? How can I stop this happening (or remove the xmlns attributes simply)?

Thanks!

Joe

Clarification: My overall task is chopping up an XML file and recombining it. So this node will be taken from beneath the root node (which has the xmlns attribute) and then integrated back into a document under a root which again has the xmlns.

+3  A: 

In your input document, <innerTag> has the logical namespace "http://xyz" because its parent <outerTag> element had that namespace. That's the way XML namespaces work.

When you ask for the <innerTag> element on its own, Scala copies the namespace declaration from the parent <outerTag>, because the namespace is a logical part of the <innerTag>, even if it wasn't explicitly stated in the initial document.

If you want to remove the namespace, you'll have to perform some additional processing to do so.

skaffman
Thanks. I reasoned something like that was the case. Any ideas on how to process it, given that % is a member of Elem but not Node (which is what I'm dealing with)?
Joe
Sorry, my Scala is a bit rusty
skaffman
+1  A: 

God, I hope I'm missing something. It can't be this awkward!

import scala.xml._
import scala.xml.tranform._

val rw = new RewriteRule { 
  override def transform(n: Node) = n match {
    case Elem(p, l, a, s, children@ _*) => Elem(p, l, a, TopScope, children: _*)
    case x => x
  }
  override def transform(ns: Seq[Node]): Seq[Node] = ns flatMap transform
}
val rt = new RuleTransformer(rw)

val input = <outerTag xmlns="http://xyz"&gt; <innerTag> </innerTag> </outerTag>

val result = input \\ "innerTag" map rt

Or am I too spoiled with Scala to think this is overly complex?

Daniel
+1  A: 

Use named parameter and Elem.copy() in Scala 2.8.0:

scala> import scala.xml._
import scala.xml._

scala> val outer = <outerTag xmlns="http://xyz"&gt;&lt;innerTag&gt;&lt;/innerTag&gt;&lt;/outerTag&gt;
outer: scala.xml.Elem = <outerTag xmlns="http://xyz"&gt;&lt;innerTag&gt;&lt;/innerTag&gt;&lt;/outerTag&gt;

scala> outer \\ "innerTag" map { case e: Elem => e.copy(scope = TopScope) }
res0: scala.xml.NodeSeq = <innerTag></innerTag>
Walter Chang
`error: value copy is not a member of scala.xml.Elem`Using latest Scala. bizarre...
Joe
@Joe copy method was added to Elem in Revision 18757 which was 4 weeks ago. If you are using the most current nightly, you will surely see it.
Walter Chang
Ah no I had the stable release (2.7.6). I'll try again with the nightly tomorrow. Thanks!
Joe
A: 

I ran into a kind of similar problem when applying transforms to sub-nodes of a document. The resulting nodes all had the xmlns on the nodes.

After completing the transformation I used the following function to 'clean' the document for the purposes of printing.

def transformForPrinting(doc : Elem) : Elem = { 
 def stripNamespaces(node : Node) : Node = {
     node match {
         case e : Elem => 
             e.copy(scope = TopScope, child = e.child map (stripNamespaces))
         case _ => node;
     }
 }
 doc.copy( child = doc.child map (stripNamespaces) )}
Paul