2011-06-27 67 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到:

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(); 

注意,這將導致情況NullReference例外您的模板標籤不包含兩個屬性標籤,每個標籤具有指定屬性。

此外,如果它不是數字,它將在解析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

這一個是有點更有效:

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 
     }; 

如果你總是一個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%同意。 –

相關問題