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

发布于 2025-01-03 10:22:26 字数 990 浏览 0 评论 0原文

我有一个 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()

I have an XML document that contains a series of item nodes that look like this:

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

and I want to LINQ it into an anonymous type like this:

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

What's the best way to pull each parameter type according to the value of its 'type' attribute? Since there are many parameter elements you wind up with root.Elements("parameter") which is a collection. The best way I can think to do it is like this by method below but I feel like there must be a better way?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

执妄 2025-01-10 10:22:26

我将使用 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 的替代方案都更简洁,假设我已经理解您想要做什么。

I would use the built-in query methods in LINQ to XML instead of XPath. Your query looks fine to me, except that:

  • If there are multiple items, you'd need to find the descendants of that instead; or just use Element if you're looking for direct descendants of the item
  • You may want to pull all the values at once and convert them into a dictionary
  • If you're using different data types for the contents, you might want to cast the element instead of using .Value
  • You may want to create a method to return the matching XElement for a given type, instead of having several queries.

Personally I don't think I'd even use a query expression for this. For example:

static XElement FindParameter(XElement element, string type)
{
    return element.Elements("parameter")
                  .SingleOrDefault(p => (string) p.Attribute("type") == type);
}

Then:

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

I suspect you'll find that's neater than any alternative using XPath, assuming I've understood what you're trying to do.

趁年轻赶紧闹 2025-01-10 10:22:26

使用XPATH - 它非常快(除了xmlreader - 但有很多 if's)

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

    }

use XPATH - it is very fast ( except xmlreader - but a lot of if's)

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

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文