ed.
ed.

Reputation: 2706

Scala - Completely remove namespace from xml

I have some xml:

<item name="ed" test="true"
  xmlns="http://www.somenamespace.com"
  xmlns:xsi="http://www.somenamespace.com/XMLSchema-instance">
  <blah>
     <node>value</node>
  </blah>
</item>

I want to go through this xml and remove all namespaces completely, no matter where they are. How would I do this with Scala?

 <item name="ed" test="true">
  <blah>
     <node>value</node>
  </blah>
</item>

I've been looking at RuleTransform and copying over attributes etc, but I can either remove the namespaces or remove the attributes but not remove the namespace and keep the attributes.

Upvotes: 7

Views: 2031

Answers (2)

mpartel
mpartel

Reputation: 4492

The following should recursively remove namespaces and from elements and attributes.

def removeNamespaces(node: Node): Node = {
  node match {
    case elem: Elem => {
      elem.copy(
        scope = TopScope,
        prefix = null,
        attributes = removeNamespacesFromAttributes(elem.attributes),
        child = elem.child.map(removeNamespaces)
      )
    }
    case other => other
  }
}

def removeNamespacesFromAttributes(metadata: MetaData): MetaData = {
  metadata match {
    case UnprefixedAttribute(k, v, n) => new UnprefixedAttribute(k, v, removeNamespacesFromAttributes(n))
    case PrefixedAttribute(pre, k, v, n) => new UnprefixedAttribute(k, v, removeNamespacesFromAttributes(n))
    case Null => Null
  }
}

It worked for at least the following test case:

<foo xmlns:xoox="http://example.com/xoox">
  <baz xoox:asd="first">123</baz>
  <xoox:baz xoox:asd="second">456</xoox:baz>
</foo>

Upvotes: 3

Thomas
Thomas

Reputation: 2095

The tags are Elem objects and the namespace is controlled by the scope value. So to get rid of it you could use:

xmlElem.copy(scope = TopScope)

However this is an immutable recursive structure so you need to do this in a recursive manner:

import scala.xml._

def clearScope(x: Node):Node = x match {
  case e:Elem => e.copy(scope=TopScope, child = e.child.map(clearScope))
  case o => o
}

This function will copy the XML tree removing the scope on all the nodes. You may have to remove the scope from the attributes too.

Upvotes: 11

Related Questions