2012-02-07 11 views
0

私は、以下のようにルーツの情報を持つxmlファイルを持っています。 usequery属性には、XML要素データが取り込まれるSQLクエリがあります。親ノード情報からXMLを作成する

<ARAXmlFormat> 
    <root name="level1" index = "1" parentid ="0" haschildren="yes"/> 
    <root name="level2" index = "2" parentid ="1" haschildren="yes" usequery="query2"/> 
    <root name="level21" index = "3" parentid ="2" haschildren="no" usequery="query1"/> 
    <root name="level22" index = "4" parentid ="2" haschildren="no" usequery="query3"/> 
    <root name="level3" index = "5" parentid ="1" haschildren="yes"/> 
    <root name="level31" index = "6" parentid ="5" haschildren="no" usequery="query4"/> 
</ARAXmlFormat> 

これから、次のようにXMLツリーを生成する必要があります。現時点では、私はすでにleve2、level21、level22、level31のための個別のXElementsを持っています。しかし、XMLを作成するにはどうすればよいのですか?上記の親情報からXML形式でこれらの要素を追加するにはどうすればよいですか?

<level1> 
    <level2> 
     <level21 attrib1 ="val1" attrib2="val2"/> 
     <level22 attrib1 ="val1" attrib2="val2"/> 
    </level2> 
    <level3> 
     <level31 attrib1 ="val1" attrib2="val2"/> 
    </level3> 
</level1> 
+0

どちらも最初のサンプル及び第2のサンプルは、整形式XML(さえ近くない)であるので、最初に私たちに示して整形式XML入力としてください:あなたの元データで

は、それが次の結果を作成します結果を構造化するコードを手助けすることができます。 –

+0

申し訳ありませんが、クライアントが提供している機密情報を削除する必要がありました。今見てください。 – user1174322

+0

」はどこから来たのですか?レベル要素の属性はどうですか?また、最初のファイルは依然として有効なXMLではありません。 ''のようなものは使用できません。 – svick

答えて

0

attrib1attrib2属性の値がどこから来た私は知りません。しかし、これまでの出力XMLツリーの階層構造が関係しているとして、あなたはこのようなものを使用して、再帰的に構築することができます:

var doc = XDocument.Load("roots.xml"); // read input xml file 

Func<int, IEnumerable<XElement>> selectChildNodes = null; // declare delegate 

selectChildNodes = parentId => doc.Elements("ARAXmlFormat").Elements().Where(
         p => p.Attribute("parentid").Value == parentId.ToString() 
       ).Select(
        x => new XElement(
             x.Attribute("name").Value, 
             selectChildNodes(Convert.ToInt32(x.Attribute("index").Value)) 
            ) 
       ); 

IEnumerable<XElement> levels = selectChildNodes(0); 

このソリューションは、入力ファイルの<root>の要素の順序とは無関係に動作します。 selectChildNodesは親ノードのインデックスを入力パラメータとして受け入れ、その要素のすべての子ノードを再帰的に返すデリゲートです。出力は、属性なしで、このようになります:

<level1> 
    <level2> 
    <level21 /> 
    <level22 /> 
    </level2> 
    <level3> 
    <level31 /> 
    </level3> 
</level1> 

new XElementと各ノードを構築するときにノード属性の値を含めることができます。

0

あなたはこのようにそれを行うことができます。

var source = XDocument.Parse(xml); // or whatever 
var sourceElems = source.Root.Elements("root"); 

var result = new XDocument(new XElement("result")); 
var resultElems = new Dictionary<int, XElement>(); 
resultElems.Add(0, result.Root); 

foreach (var sourceElem in sourceElems) 
{ 
    var resultElem = new XElement((string)sourceElem.Attribute("name")); 

    int parentId = (int)sourceElem.Attribute("parentid"); 
    resultElems[parentId].Add(resultElem); 

    resultElems.Add((int)sourceElem.Attribute("index"), resultElem); 
} 

基本的には、要素の中を歩くと、それぞれの辞書に親を見つけ、その親の子として追加し、最終的に辞書に追加、それは親自体であることができるように。これは、親がすべての子の前に常に宣言されていることを前提としています。

<result> 
    <level1> 
    <level2> 
     <level21 /> 
     <level22 /> 
    </level2> 
    <level3> 
     <level31 /> 
    </level3> 
    </level1> 
</result> 
関連する問題