簡體   English   中英

在Linq-to-Xml中處理空值和缺少列

[英]Handling null values and missing columns in Linq-to-Xml

我有一個用戶提供的DataTable,其中包含以下信息:

| Name      | Alias        |
|---------------------------
| Batman    | Dark Knight  |
| Superman  | Man of Steel |
| Spiderman | null         |

我需要將此表轉換為Xml以發送到存儲過程並獲取類似於以下內容的Xml:

<Superheroes>
    <Superhero Name="Batman" Alias="Dark Knight"/>
    <Superhero Name="Superman" Alias="Man of Steel"/>
    <Superhero Name="Spiderman"/>
</Superheroes>

我想使用Linq-to-Xml(出於學習目的)解決此問題。 這是我到目前為止的內容:

XDocument doc;

doc = new XDocument(
        new XElement("Superheroes",
        from row in table.AsEnumerable()
            select new XElement("Superhero",
                new XAttribute("Name", row.Field<string>("Name")),
                new XAttribute("Alias", row.Field<string>("Alias"))
)));

問題是蜘蛛俠行。 上面的查詢由於為null而無法正常工作。

問題

  1. 如何處理Linq-to-Xml中的空Spiderman行?

  2. 如果用戶忘記添加Alias行,則需要能夠處理該請求。 在這種情況下,別名應該是(a)完全不在Xml中,或者(b)具有空值

您可以為此編寫一個輔助函數,該函數將返回XAttributenull Linq to XML只會忽略null

private XAttribute GetAlias(DataRow row)
{
    if(row.Field<string>("Alias") != null)
    {
        return new XAttribute("Alias", row.Field<string>("Alias"));
    }
    return null;
}

並像這樣使用它。

doc = new XDocument(
    new XElement("Superheroes",
    from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            GetAlias(row)
)));

如果缺少Alias列,這也應該起作用,因為如果缺少列,則Field<T>(string)擴展方法應返回null

或者,如果你只是想有一個空字符串的屬性時,該列是丟失或值為null ,你可以做到以下幾點。

doc = new XDocument(
    new XElement("Superheroes",
    from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            new XAttribute("Alias", row.Field<string>("Alias") ?? string.Empty)
)));

另一種方法是像在第一個答案中那樣使用三元運算符: 具有三元運算符的示例

如果屬性名稱應與列標題相同,則是另一種解決方案。 您只能添加沒有空值的那些屬性:

doc = new XDocument(
         new XElement("Superheroes",
            from row in table.AsEnumerable()
            select new XElement("Superhero",
                from column in table.Columns.Cast<DataColumn>()
                let value = row.Field<string>(column)
                where value != null // just filter out nulls
                select new XAttribute(column.Caption, value)
        )));

BTW蜘蛛俠不如蝙蝠俠或超人好


實際上,您可以創建以下擴展名,該擴展名將基於表名和列名從任何DataTable構建xml(它需要System.Data.Entity.Design程序集中的PluralizationService):

public static class Extensions
{
    public static XDocument ToXml(this DataTable table)
    {
        if (String.IsNullOrEmpty(table.TableName))
           throw new ArgumentException("Table name is required");

        var pluralizationService = PluralizationService
                .CreateService(new CultureInfo("en-US"));
        string elementName = pluralizationService.Singularize(table.TableName);

        return new XDocument(
            new XElement(table.TableName,
                from row in table.AsEnumerable()
                select new XElement(elementName,
                    from column in table.Columns.Cast<DataColumn>()
                    let value = row.Field<string>(column)
                    where value != null
                    select new XAttribute(column.Caption, value)
                    )
                )
            );
    }
}

用法很簡單:

DataTable table = new DataTable("Superheroes"); // name is required
table.Columns.Add("Name");
table.Columns.Add("Alias");
table.Rows.Add("Batman", "Dark Knight");
table.Rows.Add("Superman", "Man Of Steel");
table.Rows.Add("Spiderman", null);
var doc = table.ToXml();

結果很不錯

<Superheroes>
  <Superhero Name="Batman" Alias="Dark Knight" />
  <Superhero Name="Superman" Alias="Man Of Steel" />
  <Superhero Name="Spiderman" />
</Superheroes>

您可以使用內聯if語句(使用?: operator )擴展查詢,並檢查當前行中是否設置了Alias

doc = new XDocument(
        new XElement("Superheroes",
        from row in table.AsEnumerable()
        select new XElement("Superhero",
            new XAttribute("Name", row.Field<string>("Name")),
            (row.Field<string>("Alias") != null ? new XAttribute("Alias", row.Field<string>("Alias")) : null))
));

返回null根本不會更改生成的XML,因此doc包含您希望它包含的內容:

<Superheroes>
  <Superhero Name="Batman" Alias="Dark Knight" />
  <Superhero Name="Superman" Alias="Man of Steel" />
  <Superhero Name="Spiderman" />
</Superheroes>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM