2011-11-16 8 views
2

LINQ to XMLステートメントで兄弟XElementsを返す方法は?次のXML入力から

<root> 
    <node name="one" value="1"/> 
    <node name="two" value="2"/> 
    <node name="three" value="3"/> 
    <node name="four" value="4"/> 
</root>"; 

私は次のことを生成するためにXMLにLINQを使用する必要があります。

<root> 
    <name content="one"/> 
    <value content="1"/> 
    <name content="two"/> 
    <value content="2"/> 
    <name content="three"/> 
    <value content="3"/> 
    <name content="four"/> 
    <value content="4"/> 
</root> 

このコードは名前要素ではなく、要素を生成。

var input = @" 
<root> 
    <node name=""one"" value=""1""/> 
    <node name=""two"" value=""2""/> 
    <node name=""three"" value=""3""/> 
    <node name=""four"" value=""4""/> 
</root>"; 


var xml = XElement.Parse(input); 
var query = new XElement("root", 
    from p in xml.Elements("node") 
    select new XElement("name", 
     new XAttribute("content", p.Attribute("name").Value) /*, 

     new XElement("value", new XAttribute("content", p.Attribute("value").Value)) */ 
     ) 
    ); 

私は最後の括弧内のXElement(上記コメントアウト)が含まれている場合、それは名前要素の子ではありませんが、閉じ括弧の外にそれはもはやQへのアクセス権を持っている (これはクエリの外にあります)。

2つのXElementを連結したり、何らかのXMLを生成しない別のコレクションにそれらを含める必要があるように感じます。

答えて

4

​​を使用して属性をフラット化できます。クエリ形式では、これは2 from clausesと同等です:

var query = new XElement("root", 
    from p in xml.Elements("node") 
    from a in p.Attributes() 
    select new XElement(a.Name, 
     new XAttribute("content", a.Value) 
     ) 
    ); 

実際SelectMany方法を使用して、コントラストと流暢にそれを書くことが次のようになります。

var query = new XElement("root", 
     xml.Elements("node") 
      .SelectMany(n => n.Attributes()) 
      .Select(a => new XElement(a.Name, 
       new XAttribute("content", a.Value)))); 

しかし、私はクエリ構文を見つけるために傾向がありますSelectManyの使用法のほとんどでより明確になるため、両方を混在させても問題ありませんが、1つのフォーマットまたは別のフォーマットに固執する傾向があります。

+0

これは何をしているのですか。今私が実際のコードにそれを適用できるかどうかを見てみましょう。それを理解するのに分かった。 –

+0

+1これはよりエレガントな方法です。 –

2

コードを開始点として使用する。アイテム要素にペアをラップし、子要素と置き換えます。

 var xml = XElement.Parse(input); 
     var result = new XElement("root", 
      from p in xml.Elements("node") 
      select new XElement("item", 
         new XElement("name", new XAttribute("content", p.Attribute("name").Value)), 
         new XElement("value", new XAttribute("content", p.Attribute("value").Value)))); 

     result.Descendants("item").ToList().ForEach(n => n.ReplaceWith(n.Elements())); 
+0

ああ、創造的です。アイテムをその子要素で置き換える2回目のパスをせずに済ませることができればうれしいでしょう。 。 。 –

+0

@ Ahmad'sはより洗練されていて、書かれているように私の質問にはより良い答えがありましたが、私の生産コードでうまく機能していたので、 –

+0

@ジム興味深い...そこには、ハサンのアプローチに柔軟性が加えられましたか?ただ好奇心が強いです:) –