使用 LINQ 查询 XDocument 的最佳方法?

Posted

技术标签:

【中文标题】使用 LINQ 查询 XDocument 的最佳方法?【英文标题】:Best way to query XDocument with LINQ? 【发布时间】:2012-02-29 09:51:00 【问题描述】:

我有一个 XML 文档,其中包含一系列如下所示的项目节点:

<data>
    <item>
        <label>XYZ</label>
        <description>lorem ipsum</description>
        <parameter type="id">123</parameter>
        <parameter type="name">Adam Savage</parameter>
        <parameter type="zip">90210</parameter>
    </item> 
</data>

我想将其 LINQ 转换成这样的匿名类型:

var mydata =
    (from root in document.Root.Elements("item")
    select new 
       label = (string)root.Element("label"),
       description = (string)root.Element("description"),
       id = ...,
       name = ...,
       zip = ...
     );

根据“type”属性的值提取每个参数类型的最佳方法是什么?由于有许多参数元素,您最终会得到 root.Elements("parameter") 这是一个集合。我能想到的最好方法是通过下面的方法,但我觉得必须有更好的方法?

(from c in root.Descendants("parameter") where (string)c.Attribute("type") == "id"
select c.Value).SingleOrDefault()

【问题讨论】:

【参考方案1】:

我会使用 LINQ to XML 中的内置查询方法而不是 XPath。您的查询对我来说看起来不错,除了:

如果有多个项目,则需要查找其后代;或者,如果您正在寻找该项目的直系后代,请使用 Element 您可能希望一次提取所有值并将它们转换为字典 如果您对内容使用不同的数据类型,您可能希望转换元素而不是使用.Value 您可能希望创建一个方法来为给定类型返回匹配的XElement,而不是有多个查询。

我个人认为我什至不会为此使用查询表达式。例如:

static XElement FindParameter(XElement element, string type)

    return element.Elements("parameter")
                  .SingleOrDefault(p => (string) p.Attribute("type") == type);

然后:

var mydata = from item in document.Root.Elements("item")
             select new 
                 Label = (string) item.Element("label"),
                 Description = (string) item.Element("description"),
                 Id = (int) FindParameter(item, "id"),
                 Name = (string) FindParameter(item, "name"),
                 Zip = (string) FindParameter(item, "zip")
             ;

我怀疑你会发现这比使用 XPath 的任何替代方法都更简洁,假设我已经理解你想要做什么。

【讨论】:

是的,这似乎是一个好方法,乔恩......我必须解决的另一个问题是,有时值是空字符串,因此有一个辅助方法来处理属性查询和优雅地处理在空字符串的情况下转换为正确的类型可能最有意义,谢谢【参考方案2】:

使用 XPATH - 它非常快(xmlreader 除外 - 但有 很多 的 if)

   using (var stream = new StringReader(xml))
   
    XDocument xmlFile = XDocument.Load(stream);

    var query = (IEnumerable)xmlFile.XPathEvaluate("/data/item/parameter[@type='id']");

     foreach (var x in query.Cast<XElement>())
     
         Console.WriteLine(  x.Value );
     

    

【讨论】:

那么 xpath 比使用内置的 LINQ 方法快吗? 一个从未回答过的不幸问题! @snappymcsnap 似乎答案是。请参阅Microsoft 所做的比较

以上是关于使用 LINQ 查询 XDocument 的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

当元素的名称中有冒号时,如何使用 LINQ 查询 XDocument?

在 XDocument 中按名称查询任意深度的元素

使用 XDocument 和 Linq 读取 XML - 检查元素是不是为 NULL?

C# XDocument 如何使用 linq 过滤元素

无法使用 Xdocument 和 Linq 解析 xml 字符串

linq to xml 初学 -- 查询语法