随后的 RewriteRules 不会转换在先前转换中添加的元素
Subsequent RewriteRules don't transform elements added in previous transform
import scala.xml._
import scala.xml.transform.{RewriteRule, RuleTransformer}
object TransformIssue {
def addNewElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element></element> => <element><new></new></element>
}
}
def addThingElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element>{ children@_*}</element> => <element>{ children }</element>
case <new></new> => <new><thing></thing></new>
}
}
def change(node: Node): Node =
new RuleTransformer(
addNewElement(),
addThingElement()
).transform(node).head
def changeWorkaround(node: Node): Node = {
val out1 = new RuleTransformer(
addNewElement()
).transform(node).head
new RuleTransformer(
addThingElement()
).transform(out1).head
}
}
--
import org.scalatest.{FlatSpec, FunSpec}
import org.scalatest._
class TransformIssueSpec extends FlatSpec with Matchers {
it should "apply transform to created elements" in {
val output = TransformIssue.change(<element></element>)
output should be(<element><new><thing></thing></new></element>)
} // fails
it should "work the same as the workaround imo" in {
TransformIssue.change(<element></element>) should equal(TransformIssue.changeWorkaround(<element></element>))
} // fails
}
当我们应用具有两个重写规则的转换时:第一个添加新元素,第二个向新元素添加子元素;那么第二条重写规则与第一条规则中添加的元素不匹配。
当我们在两个单独的 RuleTransformer 中应用相同的 RewriteRules 时,它会将子元素添加到第一步添加的元素中。我们希望 change
和 changeWorkaround
函数产生相同的输出。
你没有把它应用到child人身上。
def addThingElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element>{ children@_*}</element> => <element>{ transform(children) }</element>
case <new></new> => <new><thing></thing></new>
}
}
有效。
所以交易是这样的:在BasicTransformer
上,def transform(n: Node): Seq[Node]
对n
的所有children应用def transform(ns: Seq[Node]): Seq[Node]
,后一种方法应用前者到每个节点。
RuleTransformer
覆盖前一个方法,然后调用它,然后在结果上应用 RewriteRule
,因此它递归地工作。
这太令人困惑了,我花了一段时间才 re-trace 找到我从中回忆起的代码。在这里:
- RuleTransformer Node => Seq[Node] 调用 super (BasicRewrite)
- BasicRewrite Node => Seq[Node] 在 child
上调用 Seq[Node] => Seq[Node]
- BasicRewrite Seq[Node] => Seq[Node] 在每个
上调用 Node => Seq[Node]
- 由于 Node => Seq[Node] 被覆盖,如果 Seq 不为空,它递归回到 1
- RuleTransformer 现在按顺序应用每个 RewriteRule。
那么在坏掉的情况下,会是这样:
RuleTransformer.transform(<element/>)
BasicRewrite.transform(<element/>)
BasicRewrite.transform(Seq.empty)
addNewElement(<element/>)
addThingElement(<element><new/></element>)
在工作案例中它会是这样的:
RuleTransformer.transform(<element/>)
BasicRewrite.transform(<element/>)
BasicRewrite.transform(Seq.empty)
addNewElement(<element/>)
RuleTransformer.transform(<element><new/></element>)
BasicRewrite.transform(<element><new/></element>)
BasicRewrite.transform(Seq(<new/>))
RuleTransformer.transform(<new/>)
BasicRewrite.transform(<new/>)
BasicRewrite.transform(Seq.empty)
addThingElement(<new/>)
addThingElement(<element><new><thing/></new></element>)
import scala.xml._
import scala.xml.transform.{RewriteRule, RuleTransformer}
object TransformIssue {
def addNewElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element></element> => <element><new></new></element>
}
}
def addThingElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element>{ children@_*}</element> => <element>{ children }</element>
case <new></new> => <new><thing></thing></new>
}
}
def change(node: Node): Node =
new RuleTransformer(
addNewElement(),
addThingElement()
).transform(node).head
def changeWorkaround(node: Node): Node = {
val out1 = new RuleTransformer(
addNewElement()
).transform(node).head
new RuleTransformer(
addThingElement()
).transform(out1).head
}
}
--
import org.scalatest.{FlatSpec, FunSpec}
import org.scalatest._
class TransformIssueSpec extends FlatSpec with Matchers {
it should "apply transform to created elements" in {
val output = TransformIssue.change(<element></element>)
output should be(<element><new><thing></thing></new></element>)
} // fails
it should "work the same as the workaround imo" in {
TransformIssue.change(<element></element>) should equal(TransformIssue.changeWorkaround(<element></element>))
} // fails
}
当我们应用具有两个重写规则的转换时:第一个添加新元素,第二个向新元素添加子元素;那么第二条重写规则与第一条规则中添加的元素不匹配。
当我们在两个单独的 RuleTransformer 中应用相同的 RewriteRules 时,它会将子元素添加到第一步添加的元素中。我们希望 change
和 changeWorkaround
函数产生相同的输出。
你没有把它应用到child人身上。
def addThingElement(): RewriteRule = new RewriteRule {
override def transform(n: Node): Seq[Node] = n match {
case <element>{ children@_*}</element> => <element>{ transform(children) }</element>
case <new></new> => <new><thing></thing></new>
}
}
有效。
所以交易是这样的:在BasicTransformer
上,def transform(n: Node): Seq[Node]
对n
的所有children应用def transform(ns: Seq[Node]): Seq[Node]
,后一种方法应用前者到每个节点。
RuleTransformer
覆盖前一个方法,然后调用它,然后在结果上应用 RewriteRule
,因此它递归地工作。
这太令人困惑了,我花了一段时间才 re-trace 找到我从中回忆起的代码。在这里:
- RuleTransformer Node => Seq[Node] 调用 super (BasicRewrite)
- BasicRewrite Node => Seq[Node] 在 child 上调用 Seq[Node] => Seq[Node]
- BasicRewrite Seq[Node] => Seq[Node] 在每个 上调用 Node => Seq[Node]
- 由于 Node => Seq[Node] 被覆盖,如果 Seq 不为空,它递归回到 1
- RuleTransformer 现在按顺序应用每个 RewriteRule。
那么在坏掉的情况下,会是这样:
RuleTransformer.transform(<element/>)
BasicRewrite.transform(<element/>)
BasicRewrite.transform(Seq.empty)
addNewElement(<element/>)
addThingElement(<element><new/></element>)
在工作案例中它会是这样的:
RuleTransformer.transform(<element/>)
BasicRewrite.transform(<element/>)
BasicRewrite.transform(Seq.empty)
addNewElement(<element/>)
RuleTransformer.transform(<element><new/></element>)
BasicRewrite.transform(<element><new/></element>)
BasicRewrite.transform(Seq(<new/>))
RuleTransformer.transform(<new/>)
BasicRewrite.transform(<new/>)
BasicRewrite.transform(Seq.empty)
addThingElement(<new/>)
addThingElement(<element><new><thing/></new></element>)