加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala XML Building:将子节点添加到现有节点

发布时间:2020-12-16 09:29:26 所属栏目:安全 来源:网络整理
导读:我有一个XML节点,我希望随着时间的推移添加子节点: val root: Node = model/model 但我看不到像addChild()这样的方法,因为我想写下以下内容: def addToModel() = { root.addChild(subsectioncontent/subsection)} 因此,在单个调用此方法之后,根xml将是: m
我有一个XML节点,我希望随着时间的推移添加子节点:

val root: Node = <model></model>

但我看不到像addChild()这样的方法,因为我想写下以下内容:

def addToModel() = {
    root.addChild(<subsection>content</subsection>)
}

因此,在单个调用此方法之后,根xml将是:

<model><subsection>content</subsection></model>

我能看到的唯一可以附加节点的类是NodeBuffer.我错过了一些基本的东西吗?

解决方法

从这开始吧:

def addChild(n: Node,newChild: Node) = n match {
  case Elem(prefix,label,attribs,scope,child @ _*) =>
    Elem(prefix,child ++ newChild : _*)
  case _ => error("Can only add children to elements!")
}

这个方法在这里工作是因为child是Seq [Node],而newChild是一个Node,它扩展了NodeSeq,它扩展了Seq [Node].

现在,这不会改变任何东西,因为Scala中的XML是不可变的.它将生成一个具有所需更改的新节点.唯一的成本是创建一个新的Elem对象,以及创建一个新的孩子Seq.子节点本身不会被复制,只是被引用,这不会导致问题,因为它们是不可变的.

但是,如果要将子节点添加到XML层次结构中的节点,则事情会变得复杂.一种方法是使用拉链,如this blog中所述.

但是,您可以使用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.

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,然后它会得到它的孩子(它本应该被命名为孩子),在其中找到第n本书,将新孩子添加到其中,然后重构孩子并构建新节点.可行,但如果你必须做太多,拉链可能会更容易.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读