I am trying to remove an attribute with prefix in Scala using a RuleTransformer.
While the following works with unprefixed attributes:
val xml = <foo><bar attr="attval">content</bar></foo>
val rw1 = new RewriteRule {
override def transform(n: Node) = n match {
case Elem(null, "bar", a, s, children @ _*) =>
Elem(null, "bar", a.remove("attr"), TopScope, children: _*)
case x => x
}
}
val rt = new RuleTransformer(rw1)
rt(xml)
I do not succeed doing this with a prefixed attribute (note that attribute "attr" of the "bar" element has the prefix "pre"):
val xml = <foo><bar pre:attr="attval">content</bar></foo>
val rw1 = new RewriteRule {
override def transform(n: Node) = n match {
case Elem(null, "bar", a, s, children @ _*) =>
Elem(null, "bar", a.remove("attr"), TopScope, children: _*)
case x => x
}
}
val rt = new RuleTransformer(rw1)
rt(xml)
I was trying to use
a.remove("pref",TopScope,"attr")
as defined by
MetaData.remove(namespace: String, scope: NamespaceBinding, key: String)
without any success.
I am a Scala beginner, so bear with me if this is a trivial issue.
You can't remove a prefixed attribute with remove(String)
because of its implementation:
From Attribute.scala
:
def remove(key: String) =
if (!isPrefixed && this.key == key) next
else copy(next remove key)
As you can see, if the attribute is prefixed, the first branch condition is false. However, there is a different function in the same class:
def remove(namespace: String, scope: NamespaceBinding, key: String) =
if (this.key == key && (scope getURI pre) == namespace) next
else copy(next.remove(namespace, scope, key))
where the branch succeeds only if scope.getURI(pre) == namespace
, where pre
is the prefix, in your example "pre"
.
The implementation of scope.getURI
belongs to NamespaceBinding.scala
:
def getURI(_prefix: String): String =
if (prefix == _prefix) uri
else parent getURI _prefix
where all three, prefix
, uri
, and parent
are fields of the class. So in your example, prefix
must be "pre"
, uri
must be the string value of namespace
which is the first argument to remove
, and parent
must not be null, if you do not want exceptions to happen.
I do not know much about xml namespaces, but I assume you would need to have the appropriate values if your XML is well defined. If you would want to artificially craft some suitable values for this example, you could do the following (in your transform
-method):
case Elem(null, "bar", a, s, children @ _*) =>
val scope = n.scope.copy(prefix = "pre", uri = "pre", parent = n.scope)
Elem(null, "bar", a.remove("pre", scope, "attr"), TopScope, minimizeEmpty = true, children: _*)
Note that I set parent
to n.scope
, which in your example is the top-scope.
A small side-note: the apply
-method of Elem
that you use is deprecated since Scala 2.10, so I changed it to the non-deprecated method by setting minimizeEmpty
to true
.