2

我正在尝试使用 RuleTransformer 在 Scala 中删除带有前缀的属性。

虽然以下适用于无前缀属性:

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)

我没有成功使用前缀属性(注意“bar”元素的属性“attr”具有前缀“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)

我试图使用

a.remove("pref",TopScope,"attr")

定义为

MetaData.remove(namespace: String, scope: NamespaceBinding, key: String)

没有任何成功。

我是 Scala 初学者,所以如果这是一个微不足道的问题,请多多包涵。

4

2 回答 2

2

由于此处提供的有用提示,只是为了提供我能够执行上述示例的方式:

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", _, _, _) =>
        n.asInstanceOf[Elem].copy(attributes = new UnprefixedAttribute("attr", "attval", Null))
    case x => x
  }
}  
val rt = new RuleTransformer(rw1)
rt(xml)

结果:

result: scala.xml.Node = <foo><bar attr="attval">content</bar></foo>
于 2014-11-21T07:49:36.717 回答
1

remove(String)由于它的实现,您不能删除带有前缀的属性:

来自Attribute.scala

def remove(key: String) =
  if (!isPrefixed && this.key == key) next
  else copy(next remove key)

可以看到,如果属性有前缀,则第一个分支条件为假。但是,同一类中有不同的功能:

def remove(namespace: String, scope: NamespaceBinding, key: String) =
  if (this.key == key && (scope getURI pre) == namespace) next
  else copy(next.remove(namespace, scope, key))

仅当在您的示例中,前缀在scope.getURI(pre) == namespace哪里时,分支才会成功。pre"pre"

的实现scope.getURI属于NamespaceBinding.scala

def getURI(_prefix: String): String =
  if (prefix == _prefix) uri 
  else parent getURI _prefix

其中所有三个、prefixuriparent是类的字段。因此,在您的示例中,如果您不希望发生异常,则prefix必须是"pre",必须是作为第一个参数uri的字符串值,并且不能为空。namespaceremoveparent

我对 xml 命名空间了解不多,但我假设如果您的 XML 定义明确,您将需要具有适当的值。如果您想为此示例人为地制作一些合适的值,您可以执行以下操作(在您的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: _*)

请注意,我设置parentn.scope,在您的示例中是顶级范围。

一个小的旁注:您使用的apply- 方法Elem自 Scala 2.10 以来已弃用,因此我通过将其更改为非弃用方法,将其设置minimizeEmptytrue.

于 2014-11-21T02:54:50.290 回答