2016-03-22 29 views
4

から、ネストされたノードの属性のリストを作成します。私は次のようにXMLファイルを持つXMLファイル

<?xml version="1.0" encoding="utf-8"?> 
<files> 
    <file name="1"> 
     <file name="4">  
     </file> 
    </file> 
    <file name="2"> 
    </file> 
    <file name="3"> 
     <file name="5"> 
      <file name="7"> 
      </file> 
     </file> 
    </file> 
</files> 

今私は、リスト内のすべての属性nameを保存する文字列/数字/のリストを作成したいですその中にネストされたノード階層を持つ配列。私はレベルである目的のノードを知っている可能性可能性があるため、例えば上記XMLファイルの予想リストは、

(1,4 
2 
3,5,7) 

をあろう。

あなたはそのようなリストを持っているあなたのアイデアを教えてください?

更新:Jonの回答後、子ノードが同じ階層にある場合、次のようになります。

XMLファイル:

<files> 
<file name="1"> 
    <file name="4"/>  
    <file name="2"> 
     <file name="3"/> 
    </file> 
</file> 
<file name="5"/> 

所望の出力:

1,4 
1,2 
1,2,3 
5 

PS。いくつかの例を試した後、私は、同じレベルの子どもが2人以上いる場合には、最初の親とその後の子を持つ必要があることに気付きました。

答えて

3

あなたがおそらくしたいようだ:file要素

  • file要素の祖先
  • がためname属性を取るワークアウトされていないすべてfile要素については

    • それぞれの祖先を集めて一緒に参加する。

    だから私はIEnumerable<List<int>>を作成し、これは動作するはず思い

    var hierarchy = doc.Descendants("file") 
            .Where(x => x.Element("file") == null) 
            .Select(x => x.AncestorsAndSelf("file") 
               .Reverse() 
               .Select(f => (int) f.Attribute("name")) 
               .ToList()); 
    

    コンプリート例:

    using System; 
    using System.Linq; 
    using System.Xml.Linq; 
    
    class Test 
    { 
        static void Main() 
        { 
         var doc = XDocument.Load("test.xml"); 
         var hierarchy = doc.Descendants("file") 
            .Where(x => x.Element("file") == null) 
            .Select(x => x.AncestorsAndSelf("file") 
               .Reverse() 
               .Select(f => (int) f.Attribute("name")) 
               .ToList()); 
    
         foreach (var item in hierarchy) 
         { 
          Console.WriteLine(string.Join(", ", item)); 
         } 
        } 
    } 
    

    出力:

    1, 4 
    2 
    3, 5, 7 
    

    別のアプローチは、すべてのトップレベルを取ることですfile要素、それぞれ1つにつきすべての子孫を見つけます:

    using System; 
    using System.Linq; 
    using System.Xml.Linq; 
    
    class Test 
    { 
        static void Main() 
        { 
         var doc = XDocument.Load("test.xml"); 
         var hierarchy = doc.Root.Elements("file") 
            .Select(x => x.DescendantsAndSelf("file") 
               .Select(f => (int) f.Attribute("name")) 
               .ToList()); 
    
         foreach (var item in hierarchy) 
         { 
          Console.WriteLine(string.Join(", ", item)); 
         } 
        } 
    } 
    

    基本的にそれぞれのトップレベルのfile要素から「行」が得られているため、両方とも同じ結果が得られます。 - あなたは何を望む結果であるとここで

    <files> 
        <file name="1"> 
         <file name="4"/>  
         <file name="2"> 
          <file name="3"/> 
         </file> 
        </file> 
        <file name="5"/> 
    </files> 
    

    名1は、2人の子供を持つトップレベルの要素は:しかし、あなたはこのようなXMLを持っていた場合は、結果になりたいかを考えなければなりませんか?

  • +0

    あなたの答えをありがとう。 XMLファイルはどういう意味ですか? –

    +0

    @SaberJalilzadeh:申し訳ありませんが、答えのそのビットをインデントしていませんでした。もう一度見てください:) –

    +0

    まあ、非常に良い質問。このタイプのXMLファイルの場合、結果は 1,4- 1,2,3- 5となります。 –

    1

    XElement.DescendantsAndSelfを使用して階層をフラット化できます。例えば:

    var document = XDocument.Load(@"d:\xml.xml"); 
    var list = document.Root.Elements() 
            .Select(x=>string.Join(",", 
             x.DescendantsAndSelf().Select(d=>d.Attribute("name").Value))) 
            .ToList(); 
    

    上記サンプルの結果は、各要素が階層にコンマ区切りの名前を含むタイプList<string>です。柔軟性を高めるために各要素に階層のIEnumerable<string>が必要な場合は、selectステートメントからstring.Joinを削除してください。

    EDIT
    答えは、各ファイルが子供のように一つだけのファイルを持って、あなたのオリジナルのポストに基づいて掲載されています。ファイルの子として複数のファイルがある場合は、answerに記載されているようにAncestorsAndSelfを使用して問題を解決する必要があります。

    +0

    答えは、ファイルには子として1つのファイルしかありません。ファイルの子として複数のファイルがある場合は、['AncestorsAndSelf'](https://msdn.microsoft.com/en-us/library/bb346865(v=vs.110))を使用して問題を解決する必要があります。 aspx)を参照してください(Jonの[answer](http://stackoverflow.com/a/36149478/3110834))。 –

    +0

    ありがとうございます、あなたは正しいです! –

    関連する問題