object Main {
def main(args: Array[String]): Unit = {
val rootCopy:Node=processNodeSeq(root).asInstanceOf[Node]
}
def processNodeSeq(nodeSeq:NodeSeq): NodeSeq ={
val resultNode:NodeSeq = if (nodeSeq.size > 1)
processNode(nodeSeq.apply(0)) ++: processNodeSeq(nodeSeq.drop(1))
else
processNode(nodeSeq.apply(0));
resultNode;
}
def processNode(node:Node): NodeSeq={
node match{
case e: Elem => new Elem(e.prefix, e.label, e.attributes, e.scope, true, (processNodeSeq(e.child)):_*);
case t: Text => new Text(t.text);
case n => null;
}
}
}
F#のLINQ For XMLの場合と違うのは、processNode関数のElem(要素)の処理部分です.LINQ For XMLでは、要素のXElementをコンストラクトしてから、それに属性を加えたり、子のノードを加えたりできました.しかしScalaではそういうことはできません.何故かというとScalaのElemは immutable objectだからです.つまりいったんコンストラクトしたら変えられません.なので、
new Elem(e.prefix, e.label, e.attributes, e.scope, true, (processNodeSeq(e.child)):_*);
new Elem(prefix: String, label: String, attributes1: MetaData, scope: NamespaceBinding, minimizeEmpty: Boolean, child: Node*)
という形をしています.最初コーディングするときにchild: NodeSeqかと思ったんですが違いました.child: Node*はvararg(可変個数のパラメータ)を表します.processNodeSeqはNodeSeqを返しますが、これに対して":_*"を記述することにより、コンパイラーにNodeSeqをvarargに展開して解釈するように指定してくれるようです.
Scalaでこんなに短く書けるとは思いませんでした.初心者でもやってみるとできますね.
でしたが、Scalaが作成してくれたのは