Linq到Xml - 空元素

时间:2011-12-06 00:02:39

标签: c# linq-to-xml

我正在使用Linq解析xml文档,但我遇到的情况是我不知道如何处理这个问题。我发现/尝试过的所有东西似乎都不起作用。正如您在下面看到的(非常简单的场景)OrderAmount为空。这是一个十进制字段。当我试图在LINQ中处理它时,它一直在轰炸。我尝试过使用deimcal ?,使用null检查等,似乎没有任何工作(很可能是用户错误)。任何建议,将不胜感激。

当元素是非字符串(如小数)并且为空时如何处理?

XML:

<Orders>
  <Order>
    <OrderNumber>12345</OrderNumber>
    <OrderAmount/>
  </Order>
</Orders>

LINQ:

List<Order> myOrders = from orders in xdoc.Descendants("Order")
                       select new Order{
                       OrderNumber = (int)orders.Element("OrderNumber"),
                       OrderAmount = (decimal?)orders.Element("OrderAmount"),


}.ToList<Order>();

4 个答案:

答案 0 :(得分:4)

仅当元素实际为XElement时,decimal?null的演员才会返回null

我认为最可读的解决方案是这样的:

elem.IsEmpty ? null : (decimal?)elem

如果您经常使用它,您可能希望将其放入扩展方法中。或者只是在LINQ查询中使用let,不要重复选择元素的代码。

from orders in xdoc.Descendants("Order")
let amountElem = orders.Element("OrderAmount")
select new Order
{
    OrderNumber = (int)orders.Element("OrderNumber"),
    OrderAmount = amountElem.IsEmpty ? null : (decimal?)amountElem
}

如果您可以更改XML,另一个选项就是省略代表null的元素。它应该与您已有的代码一起使用。

编辑:扩展方法如下所示:

static class XElementExtensions
{
    public static decimal? ToNullableDecimal(this XElement elem)
    {
        return elem.IsEmpty ? null : (decimal?)elem;
    }
}

你会像这样使用它:

OrderAmount = orders.Element("OrderAmount").ToNullableDecimal()

答案 1 :(得分:3)

怎么样

OrderAmount = String.IsNullOrEmpty(orders.Element("OrderAmount").Value) ? 
                  default(decimal?) : Decimal.Parse(orders.Element("OrderAmount").Value),

根据svick的评论,这可能更安全

OrderAmount = String.IsNullOrEmpty(orders.Element("OrderAmount").Value) ? 
                  default(decimal?) : (decimal)orders.Element("OrderAmount"),

答案 2 :(得分:0)

我认为你想要元素的价值而不是元素本身。

编辑:如果你真的开始保持演员表,那么这是一个通过单元测试,你可以使用它来获得一种可能更令人愉悦的格式:

    private XDocument BuildDocument()
    {
        var myAmount = new XElement("OrderNumber", 12345);
        var myNumber = new XElement("OrderAmount");
        var myOrder = new XElement("Order", myAmount, myNumber);
        var myOrders = new XElement("Orders", myOrder);
        return new XDocument(myOrders);
    }

    private class Order
    {
        public int OrderNumber { get; set; }
        public decimal? OrderAmount { get; set; }
    }

    [TestMethod]
    public void TestMethod()
    {
        var myDoc = BuildDocument();
        List<Order> myOrders = (from orders in myDoc.Descendants("Order")
                               select new Order
                               {
                                   OrderNumber = (int)orders.Element("OrderNumber"),
                                   OrderAmount = GetAmount(orders.Element("OrderAmount"))
                               }).ToList<Order>();
    }

    private static decimal? GetAmount(XElement e)
    {
        if (e == null || string.IsNullOrEmpty(e.Value))
        {
            return 0.0M;
        }
        return (decimal?)e;
    }

(你仍然需要添加代码来处理OrderAmount的值类似于“Asdf”的情况)

答案 3 :(得分:0)

您如何在Order类中声明OrderAmount?尝试声明

public decimal? OrderAmount { get; set; }