如何解决Scala XML 构建:向现有节点添加子节点
那么从这个开始:
def addChild(n: Node, newChild: Node) = n match {
case Elem(prefix, label, attribs, scope, child @ _*) =>
Elem(prefix, label, attribs, scope, child ++ newChild : _*)
case _ => error("Can only add children to elements!")
}
该方法++
在这里有效,因为child
是 a Seq[Node]
,并且newChild
是 a Node
,它扩展了NodeSeq
,扩展了Seq[Node]
。
现在,这并没有改变任何东西,因为 Scala 中的 XML 是不可变的。它将生成一个具有所需更改的新节点。唯一的成本是创建一个新Elem
对象以及创建一个新Seq
的子对象。子节点本身不会被复制,只是被引用,这不会导致问题,因为它们是不可变的。
但是,如果您将子节点添加到 XML 层次结构中的节点,事情就会变得复杂。一种方法是使用拉链,如本博客中所述。
但是,您可以将scala.xml.transform
, 与将更改特定节点以添加新子节点的规则一起使用。首先,编写一个新的转换器类:
class AddChildrenTo(label: String, newChild: Node) extends RewriteRule {
override def transform(n: Node) = n match {
case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild)
case other => other
}
}
然后,像这样使用它:
val newXML = new RuleTransformer(new AddChildrenTo(parentName, newChild)).transform(oldXML).head
在 Scala 2.7 上,替换head
为first
.
Scala 2.7 上的示例:
scala> val oldXML = <root><parent/></root>
oldXML: scala.xml.Elem = <root><parent></parent></root>
scala> val parentName = "parent"
parentName: java.lang.String = parent
scala> val newChild = <child/>
newChild: scala.xml.Elem = <child></child>
scala> val newXML = new RuleTransformer(new AddChildrenTo(parentName, newChild)).transform(oldXML).first
newXML: scala.xml.Node = <root><parent><child></child></parent></root>
如果仅父级还不够,则可以使获取正确元素变得更加复杂。但是,如果您需要将子项添加到具有特定索引的通用名称的父项中,那么您可能需要走拉链的方式。
例如,如果您有<books><book/><book/></books>
,并且您想添加<author/>
到第二个,那么使用规则转换器很难做到这一点。你需要一个 RewriteRule against books
,然后它会得到它child
(它真的应该被命名为children
),在其中找到第 n个 book
,将新的子节点添加到其中,然后重新组合子节点并构建新节点。可行,但如果你必须这样做太多,拉链可能会更容易。
解决方法
我有一个 XML 节点,我想随着时间的推移向其中添加子节点:
val root: Node = <model></model>
但是我看不到诸如addChild()之类的方法,因为我想写一些类似的东西:
def addToModel() = {
root.addChild(<subsection>content</subsection>)
}
因此,在一次调用此方法后,根 xml 将是:
<model><subsection>content</subsection></model>
我能看到的唯一能够附加节点的类是 NodeBuffer。我在这里错过了一些基本的东西吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。