2011-06-27 42 views
0

これを行う方法はありますか? 両方のプロパティ値を取得する必要があります。 XMLには常に2つのプロパティしかありません。C#LINQ to XMLを使用して同じ名前の複数の要素を読み取る

私のxml:

<Template name="filename.txt"> 
    <Property name="recordSeparator">\r\n</Property> 
    <Property name="fieldCount">16</Property> 
</Template> 

のLINQ:

  var property = from template in xml.Descendants("Template") 
         select new 
            { 
             recordDelim = template.Elements("Property").Where(prop => prop.Attribute("name").Value == "recordSeparator") 
                .Select(f => new { f.Value }), 
             fieldCount = template.Elements("Property").Where(prop => prop.Attribute("name").Value == "fieldCount") 
                .Select(f => new { f.Value }) 
            }; 
+0

質問を明確にしてくださいあなたがしようとしていること。 http://tinyurl.com/so-hints –

+0

を読んでください。単一のテンプレートに複数の区切り文字やfieldCountプロパティが必要ですか? Select()はIEnumerable の場合、IEnumerable を返します。これは、recordDelimとfieldCountの両方がIEnumerable のタイプであることを意味します。それは匿名のオブジェクトに必要なものですか? –

+0

@kornelijepetak、xmlは常に同じで、これらの2つのプロパティのみを持ちます。 – hs2d

答えて

3

「より良い方法」は、パフォーマンス、シンプルさなど、達成しようとしていることが何であるかによって異なります。

私はあなたが匿名のクラスで取得しようとしているものを含むクラスを作成すると思います。

public class Item { 
    public String Separator { get; set; } 
    public int FieldCount { get; set; } 
} 

、その後、私はLINQを変更します:これはあなたのテンプレートタグは、指定された属性を持つ2個のプロパティタグ、それぞれが含まれていない場合にはNullReference例外が発生しますことを

var templates = from template in xml.Descendants("Template") 
       let children = template.Elements("Property") 
       select new Item() { 
        Separator = children.First(tag=>tag.Attribute("name").Value == "recordSeparator").Value, 
        FieldCount = Int32.Parse(children.First(tag=>tag.Attribute("name").Value == "fieldCount").Value) 
       }; 

List<Item> items = templates.ToList(); 

注意。

また、数値でない場合は、FieldCountから整数を解析する際に例外がスローされます。

アイデア:

XMLが生成された場合は、あなた自身で、あなたはそれが何かをしない理由フォーマット、です変更することができます。

<Template> 
    <Name>filename.txt</Name> 
    <RecordSeparator>\r\n</RecordSeparator> 
    <FieldCount>16</FieldCount> 
</Template> 

それは読み取り、解析する方が簡単だし、それはです少し短く最後に

は、私はこれは私がそれを行うだろうかだと思います。このクラスを持つ

public class Item 
{ 
    public String FileName { get; set; } 
    public String Separator { get; set; } 
    public int FieldCount { get; set; } 
} 

と、このプライベートメソッド:私はコード内で行うことができ

private Item GetItemFromTemplate(XElement node) 
{ 
    return new Item() { 
     FileName = node.Element("Name").Value, 
     Separator = node.Element("RecordSeparator").Value, 
     FieldCount = Int32.Parse(node.Element("FieldCount").Value) 
    }; 
}  

XDocument doc = XDocument.Load("myfile.txt"); 

List<Item> items = (from template in doc.Elements("Template") 
        select GetItemFromTemplate(template)).ToList(); 
+0

アイデアありがとう!私はxmlの構造を変更するつもりだと思うのは、実際に読みやすく解析する方が簡単だからです。 – hs2d

+0

あなたは私が作った編集を検討したいかもしれません。 LINQクエリを簡素化する。 –

+0

さて、答えにかなりの努力を払っています:)。同意回答は+1ですが。 –

1

この1つはもう少し効率的である:

var properties = 
    from template in xml.Descendants("Template") 
    let propertyNodes = template.Elements("Property") 
     .Select(arg => new { Name = arg.Attribute("name").Value, Value = arg.Value }) 
    select 
     new 
     { 
      recordDelim = propertyNodes.Single(arg => arg.Name == "recordSeparator").Value, 
      fieldCount = propertyNodes.Single(arg => arg.Name == "fieldCount").Value 
     }; 

あなたは常に1つのTemplateノードを使用している場合:

var propertyNodes = xml.XPathSelectElements("/Template/Property") 
    .Select(arg => new { Name = arg.Attribute("name").Value, arg.Value }) 
    .ToList(); 

var properties = 
    new 
    { 
     recordDelim = propertyNodes.Single(arg => arg.Name == "recordSeparator").Value, 
     fieldCount = propertyNodes.Single(arg => arg.Name == "fieldCount").Value 
    }; 
+0

これはもちろん動作しますが、LINQクエリを実行しているメソッド内でのみこの情報(区切り文字、カウント)が必要な場合を除き、匿名オブジェクトは強制しません。さもなければ、私はそれがカスタム作成されたクラスと一緒に行くことは賢明で(そしておそらく必要でさえ)あると思う。 –

+0

@kornelijepetak - 100%が同意します。 –

関連する問題