Linq to Xml - пустой элемент - PullRequest
       4

Linq to Xml - пустой элемент

3 голосов
/ 06 декабря 2011

Я анализирую документ xml с Linq, но сталкиваюсь со сценарием, в котором я не уверен, как обрабатывать обработку.Все, что я нашел / попробовал, похоже, не работает.Как вы можете видеть ниже (очень простой сценарий), где OrderAmount пусто.Это десятичное поле.Когда я пытаюсь справиться с этим в LINQ, он продолжает бомбить.Я попытался использовать deimcal ?, с помощью проверки на ноль и т. Д., Кажется, ничего не работает (скорее всего, ошибка пользователя).Мы ценим любые предложения.

Как вы справляетесь, когда элемент не является строкой (например, десятичным) и пуст?

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 ]

4 голосов
/ 06 декабря 2011

Приведение от XElement к decimal? возвращает null только тогда, когда элемент действительно null.

Я думаю, что наиболее читаемое решение выглядит примерно так:

elem.IsEmpty ? null : (decimal?)elem

Возможно, вы захотите поместить это в метод расширения, если вы используете его часто. Или просто используйте let в своем запросе LINQ, чтобы не повторять код, который выбирает элемент.

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()
3 голосов
/ 06 декабря 2011

Как насчет

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"),
0 голосов
/ 06 декабря 2011

Как вы объявили OrderAmount в своем классе Order?Попробуйте объявить

public decimal? OrderAmount { get; set; }
0 голосов
/ 06 декабря 2011

Я думаю, вам нужно значение элемента, а не сам элемент.

Редактировать: Если вы действительно хотите сохранить актерский состав, вот проходной юнит-тест, с которым вы можете работать, чтобы получить формат, возможно, более приятный для глаз:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...