Здание Scala XML: Добавление детей к существующим Узлам

У меня Есть Узел XML, к которому я хочу добавить детей со временем:

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

Но я не вижу методы, такие как addChild (), поскольку я хотел бы записать что-то вроде:

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

Таким образом, после единственного вызова к этому методу корень xml был бы:

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

Единственный класс I видит, что это имеет способность добавить Узел, NodeBuffer. Я пропускаю что-то фундаментальное здесь?

22
задан BefittingTheorem 4 February 2010 в 11:19
поделиться

4 ответа

Начнем с этого:

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!")
}

Метод ++ работает здесь, потому что дочерний элемент является Seq [Node] и newChild - это Node , который расширяет NodeSeq , который расширяет Seq [Node] .

Это ничего не меняет, потому что XML в Scala неизменяем. Будет создан новый узел с необходимыми изменениями.Единственная стоимость - это создание нового объекта 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 на .

Пример на 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>

Вы можете усложнить получение нужного элемента, если одного родителя недостаточно. Однако, если вам нужно добавить потомка к родителю с общим именем определенного индекса, то вам, вероятно, придется пойти по пути застежек-молний.

Например, если у вас есть , и вы хотите добавить ко второму, это было бы сложно сделать с помощью преобразователя правил. Вам понадобится RewriteRule против книг , которое затем получит его дочерний элемент (который действительно должен был называться children ), найдите n book в них, добавьте к нему новый дочерний элемент, а затем перекомпонуйте дочерние элементы и создайте новый узел. Это выполнимо, но если вам придется делать это слишком много, может быть проще застегнуть молнию.

30
ответ дан 29 November 2019 в 04:06
поделиться

Это известные ошибки IDE. Вы пробовали Пакет исправлений IDE ?

-121--4321652-

Ответом является отношение Родительский/Дочерний объект, существующее в Qt. Если родительский объект выходит из области действия или уничтожается любым другим способом, Qt гарантирует, что все его дочерние объекты будут уничтожены в.

Более подробную информацию об этом поведении можно найти здесь - > http://doc.trolltech.com/4.4/objecttrees.html

-121--4631710-

В Scala xml узлы являются неизменяемыми, но может сделать это:

var root = <model/>

def addToModel(child:Node) = {
  root = root match {
    case <model>{children@ _*}</model> => <model>{children ++ child}</model>
    case other => other
  }
}

addToModel(<subsection>content</subsection>)

Он переписывает новый xml, делая копию старого и добавляя узел в качестве дочернего.

Edit: Брайан предоставил больше информации, и я решил, что другое соответствует.

Чтобы добавить дочерний узел в произвольный узел в 2.8, можно сделать следующее:

def add(n:Node,c:Node):Node = n match { case e:Elem => e.copy(child=e.child++c) }

Это вернет новую копию родительского узла с добавленным дочерним узлом. Предполагая, что вы сложили свои дочерние узлы по мере того, как они стали доступны:

scala> val stack = new Stack[Node]()
stack: scala.collection.mutable.Stack[scala.xml.Node] = Stack()

После того, как вы решили, что вы закончите с извлечением дочерних элементов, вы можете обратиться к родителю, чтобы добавить все дочерние элементы в стек следующим образом:

stack.foldRight(<parent/>:Node){(c:Node,n:Node) => add(n,c)}

Я не имею понятия о производительности использования Stack и Right , так что в зависимости от того, сколько детей вы сложили нет, вам придется Затем может потребоваться вызвать и stack.clear . Надеюсь, это заботится о неизменной природе Node , но также и о вашем процессе, как вам нужно.

8
ответ дан 29 November 2019 в 04:06
поделиться

Поскольку XML является неизменяемым, вы должны создавать новый каждый раз, когда вы хотите добавить узел, вы можете использовать Сопоставление образов для добавления вашего нового узла:

    var root: Node = <model></model>
    def addToModel(newNode: Node) = root match {
       //match all the node from your model
       // and make a new one, appending old nodes and the new one
        case <model>{oldNodes@_*}</model> => root = <model>{oldNodes}{newNode}</model>
    }
    addToModel(<subsection>content</subsection>)
3
ответ дан 29 November 2019 в 04:06
поделиться

В обычном режиме Scala все экземпляры Node, Elem и т.д. неизменны. Вы можете работать по-другому:

  scala> val child = <child>foo</child>
  child: scala.xml.Elem = <child>foo</child>

  scala> val root = <root>{child}</root>
  root: scala.xml.Elem = <root><child>foo</child></root>

Смотрите http://sites.google.com/site/burakemir/scalaxbook.docbk.html для получения более подробной информации.

2
ответ дан 29 November 2019 в 04:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: