Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have since learned more and presented what I deem to be a superior solution in another answer. I have also fixed this one, as I noticed I was failing to account for the <code>subnode</code> restriction.</p> <p>Thanks for the question! I just learned some cool stuff when dealing with XML. Here is what you want:</p> <pre><code>def updateVersion(node: Node): Node = { def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] = for(subnode &lt;- ns) yield subnode match { case &lt;version&gt;{ _ }&lt;/version&gt; if mayChange =&gt; &lt;version&gt;2&lt;/version&gt; case Elem(prefix, "subnode", attribs, scope, children @ _*) =&gt; Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*) case Elem(prefix, label, attribs, scope, children @ _*) =&gt; Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*) case other =&gt; other // preserve text } updateNodes(node.theSeq, false)(0) } </code></pre> <p>Now, explanation. First and last case statements should be obvious. The last one exists to catch those parts of an XML which are not elements. Or, in other words, text. Note in the first statement, though, the test against the flag to indicate whether <code>version</code> may be changed or not.</p> <p>The second and third case statements will use a pattern matcher against the object Elem. This will break an element into <em>all</em> its component parts. The last parameter, "children @ _*", will match children to a list of anything. Or, more specifically, a Seq[Node]. Then we reconstruct the element, with the parts we extracted, but pass the Seq[Node] to updateNodes, doing the recursion step. If we are matching against the element <code>subnode</code>, then we change the flag mayChange to <code>true</code>, enabling the change of the version.</p> <p>In the last line, we use node.theSeq to generate a Seq[Node] from Node, and (0) to get the first element of the Seq[Node] returned as result. Since updateNodes is essentially a map function (for ... yield is translated into map), we know the result will only have one element. We pass a <code>false</code> flag to ensure that no <code>version</code> will be changed unless a <code>subnode</code> element is an ancestor.</p> <p>There is a slightly different way of doing it, that's more powerful but a bit more verbose and obscure:</p> <pre><code>def updateVersion(node: Node): Node = { def updateNodes(ns: Seq[Node], mayChange: Boolean): Seq[Node] = for(subnode &lt;- ns) yield subnode match { case Elem(prefix, "version", attribs, scope, Text(_)) if mayChange =&gt; Elem(prefix, "version", attribs, scope, Text("2")) case Elem(prefix, "subnode", attribs, scope, children @ _*) =&gt; Elem(prefix, "subnode", attribs, scope, updateNodes(children, true) : _*) case Elem(prefix, label, attribs, scope, children @ _*) =&gt; Elem(prefix, label, attribs, scope, updateNodes(children, mayChange) : _*) case other =&gt; other // preserve text } updateNodes(node.theSeq, false)(0) } </code></pre> <p>This version allows you to change any "version" tag, whatever it's prefix, attribs and scope.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload