使用XML-to-Linq获取XML元素值

本文关键字:元素 XML 获取 XML-to-Linq 使用 | 更新日期: 2023-09-27 18:28:54

XML im查询的一个片段是

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<metadata created="2014-11-03T18:13:02.769Z" xmlns="http://example.com/ns/mmd-2.0#" xmlns:ext="http://example.com/ns/ext#-2.0">
    <customer-list count="112" offset="0">
        <customer id="5f6ab597-f57a-40da-be9e-adad48708203" type="Person" ext:score="100">
            <name>Bobby Smith</name>
            <gender>male</gender>
            <country>US</country>
            <birth-span>
                <start>1965-02-18</start>
                <end>false</end>
            </birth-span>

我编写的获取元素的代码是

    GetCustomer = from c in XDoc.Descendants(ns + "customer")
                      select
                      new Customer
                      {
                          Name = c.Element(ns + "name").ToString(),
                          Gender = Convert.ToString(c.Element(ns + "gender")),
                          BeginDate = c.Elements("birth-span").Any() ? c.Element("start").Value.ToString() : "No data found"

我遇到的问题是birth-span,如果出生跨度存在(有些记录不包含出生跨度元素),我似乎永远不会得到值。对于包含出生跨度元素的记录,我添加了不起作用的名称空间变量(抛出对象未设置为实例的错误)

 BeginDate = c.Elements(ns + "birth-span").Any() ? c.Element(ns + "start").Value.ToString() : "No data found"

我添加了不同的变体,但要么得到了值No Data found,要么出现了错误(似乎是对象未设置为实例)。有人看到我做错了什么吗?

使用XML-to-Linq获取XML元素值

您通过以下操作将start视为c(或customer)的直接后代:

BeginDate = c.Elements("birth-span").Any() ?
    c.Element("start").Value.ToString() :
    "No data found"

当您真正想将start视为birth-span元素的直接后代时,如下所示:

BeginDate = c.Elements("birth-span").Any() ?
    c.Element("birth-span").Element("start").Value.ToString() :
    "No data found"

不过还有改进的空间。是否存在零个或一个birth-span元素,或零个或多个?因为它看起来是零或一,你可以这样做,让它变得更清晰:

var customers = from c in doc.Descendants("customer")
                let birthSpan = c.Element("birth-span")
                select new
                {
                    Name = c.Element("name").Value,
                    Gender = c.Element("gender").Value,
                    BeginDate = birthSpan == null ?
                        "No data found" :
                        birthSpan.Element("start").Value
                };

此外,不需要对其中任何一个调用Convert.ToString.ToString()。如果你想要一个string.Value()就可以了。如果你真的想把它键入其他类型,直接把它强制转换,让转换运算符来做:

var customers = from c in doc.Root.Descendants("customer")
                let birthSpan = c.Element("birth-span")
                select new
                {
                    Name = (string)c.Element("name"),
                    Gender = (string)c.Element("gender"),
                    BeginDate = birthSpan == null ?
                        (DateTime?)null :
                        (DateTime?)birthSpan.Element("start")
                };

这里有一篇关于这方面的好文章。

相关文章: