2011-01-07 14 views
0

xml.Nodeから一連のパスを収集したいとします。私は作業コードを持っていますが、それは醜いです。私は(または多分よりよい解決策?)それをクリーンアップするためにいくつかの助けが欲しいノードからパスを収集する

import xml._ 

def paths(node: Node): Set[String] = { 
    def inner(base: String, node: Node): Set[String] = { 
    if (node.isInstanceOf[Elem]) { 
     val newBase = "%s/%s".format(base, node.label) 
     val selfAndChildren = node.child.flatMap(
     inner(newBase, _)).toSet.asInstanceOf[Set[String]] + newBase 
     val attributes = node.attributes.map(a => 
     "%s/@%s".format(newBase, a.key)).toSet.asInstanceOf[Set[String]] 
     selfAndChildren ++ attributes 
    } else Set.empty[String] 
    } 
    inner("", node) 
} 

は使用方法:

scala> val x = <a><b z="true"><c>3</c></b></a> 
x: scala.xml.Elem = <a><b z="true"><c>3</c></b></a> 

scala> paths(x)        
res1: Set[String] = Set(/a/b/c, /a/b, /a/b/@z, /a) 

は、私は好きではない何か:

  • 型システムを私は結果をキャストすることを余儀なくされましたtoSet
  • 私はXML APIで何者かの完全修飾パスを得るために何かを期待しましたElement
  • isInstanceOf[T]チェックを使用するのは好きではありませんが、動作するようにパターンマッチングを取得できませんでした。
  • あまりにも冗長です。
+0

パスに属性があるのはなぜですか?あなたの例のパスは/ a/b/c、/ a/b、/ aだと思っていました。/a/b/@ zについて混乱している。 –

+0

私の特別なクッキーの必要性は、私が出力でこれを必要とすることを指示します。詳細は、ノードと属性を厄介なベンダーフレームワークのAPIに複製するように構成されたビルダーを作っていることです。興味のあるすべてのパスをプラグインして、XMLを歩いていきます。一致するすべてのパスがベンダーのAPIで作成され、値がコピーされます。私は属性をコピーする必要があるので、ここに存在します。代わりに(xpathのように)/ a/b @ zでなければなりませんが、正確な表記は重要ではありません。 – Synesso

答えて

2

純粋なスタイルではなく、アルゴリズムを見て:

def paths(node: Node): Set[String] = { 
    def inner(base: String, node: Node): Set[String] = node match { 
    case n:Elem => 
     val newBase = base + "/" + n.label 
     (Set(newBase) 
     ++ n.child.flatMap(inner(newBase, _)) 
     ++ n.attributes.map(base + "/@" + _.key)) 
    case _ => Set.empty 
    } 
    inner("", node) 
} 

私は冗長性、インスタンスのチェックやクラスキャストに役立つと思います。

関連する問題