Depuis, j'ai appris de plus en plus et nous a présenté ce que j'estime être une meilleure solution dans une autre réponse. J'ai aussi corrigé cela, comme j'ai remarqué que j'étais en ne tenant pas compte de l' subnode
restriction.
Merci pour la question! J'ai juste appris quelques trucs cool lorsque vous traitez avec XML. Voici ce que vous voulez:
def updateVersion(node: Node): Node = {
def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] =
for(subnode <- ns) yield subnode match {
case <version>{ _ }</version> if mayChange => <version>2</version>
case Elem(prefix, "subnode", attribs, scope, children @ _*) =>
Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*)
case Elem(prefix, label, attribs, scope, children @ _*) =>
Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*)
case other => other // preserve text
}
updateNodes(node.theSeq, false)(0)
}
Maintenant, l'explication. Premier et dernier cas, les déclarations devraient être évidentes. La dernière il en existe un pour rattraper ces pièces d'un XML qui ne sont pas des éléments. Ou, en d'autres termes, le texte. Remarque dans la première déclaration, cependant, le test contre le drapeau pour indiquer si version
peut être changé ou pas.
Le deuxième et le troisième cas, les déclarations utiliser un modèle de matcher l'encontre de l'objet Elem. Cela permettra de briser un élément dans toutes ses composantes. Le dernier paramètre, "les enfants @ _*", sera de faire correspondre les enfants à une liste de quoi que ce soit. Ou, plus précisément, Seq[Noeud]. Ensuite, nous reconstruisons l'élément, avec les parties, nous avons extrait, mais passer le Seq[Nœud] pour updateNodes, faire de la récursivité de l'étape. Si nous sommes correspondant à l'encontre de l'élément subnode
, puis nous changer le drapeau mayChange d' true
, permettant le changement de version.
Dans la dernière ligne, nous utilisons nœud.theSeq pour générer un Seq[Nœud] de Nœud, et (0) pour obtenir le premier élément de la séquence Seq[Nœud] retournée comme résultat. Depuis updateNodes est essentiellement une fonction map (pour ... le rendement est traduit en plan), nous savons que la raison n'ont qu'un seul élément. Nous avons passer un false
drapeau pour s'assurer qu'aucun version
pourront être modifiés, à moins d'un subnode
élément est un ancêtre.
Il y a une manière légèrement différente de le faire, c'est plus puissant mais un peu plus verbeux et obscure:
def updateVersion(node: Node): Node = {
def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] =
for(subnode <- ns) yield subnode match {
case Elem(prefix, "version", attribs, scope, Text(_)) if mayChange =>
Elem(prefix, "version", attribs, scope, Text("2"))
case Elem(prefix, "subnode", attribs, scope, children @ _*) =>
Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*)
case Elem(prefix, label, attribs, scope, children @ _*) =>
Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*)
case other => other // preserve text
}
updateNodes(node.theSeq, false)(0)
}
Cette version vous permet de modifier tout "version" de la balise, quel que soit son préfixe, attribs et la portée.