MarioPT Ответов: 2

XML-файл C# удаляет дубликаты и суммирует значения с помощью LINQ


По сути, я удаляю дублированные записи и суммирую их значения, чтобы иметь только одну из каждой записи.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        //File
        const string FILE = "ccc.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILE);

            List <XElement> originalInvoices = doc.Descendants("Invoice").ToList();

            var groups = originalInvoices.GroupBy(x => (string)x.Element("Hash")).ToList();

            var finalInvoices = groups.Select(x => new {
                unit = x.Descendants("UnitPrice").Sum(z => (decimal)z),
                credit = x.Descendants("CreditAmount").Sum(z => (decimal)z),
                tax = x.Descendants("TaxPayable").Sum(z => (decimal)z),
                net = x.Descendants("NetTotal").Sum(z => (decimal)z),
                gross = x.Descendants("GrossTotal").Sum(z => (decimal)z),
                first = x.First()
            }).ToList();

            foreach (var finalInvoice in finalInvoices)
            {
                finalInvoice.first.Element("Line").SetElementValue("UnitPrice", finalInvoice.unit);
                finalInvoice.first.Element("Line").SetElementValue("CreditAmount", finalInvoice.credit);
                finalInvoice.first.Element("DocumentTotals").SetElementValue("TaxPayable", finalInvoice.tax);
                finalInvoice.first.Element("DocumentTotals").SetElementValue("NetTotal", finalInvoice.net);
                finalInvoice.first.Element("DocumentTotals").SetElementValue("GrossTotal", finalInvoice.gross);
            }

            doc.Element("SalesInvoices").ReplaceWith(new XElement("SalesInvoices", finalInvoices.Select(x => x.first)));
            Console.WriteLine(doc);
            Console.ReadKey();

        }
    }
}


Проблема в том, что мой код взрывается, когда он достигает следующей строки в конце:
`doc.Element("SalesInvoices").ReplaceWith(new XElement("SalesInvoices", finalInvoices.Select(x => x.first)));`


С следующее сообщение об ошибке: `An unhandled exception of type 'System.NullReferenceException' occurred in ConsoleApplication2.exe`

Я не могу это исправить мой файл вот этот: [В формате XML] &ЛТ;?в XML версия="1.0" кодирование="UTF-8"?&ГТ; &ЛТ;AuditFile префиксом xmlns="урна:ОЭСР:StandardAudit - Pastebin.com[^]

В принципе, код должен удалить Invoices повторный Hash и суммировать значения UnitPrice, CreditAmount, TaxPayable, NetTotal, и GrossTotal, где UnitPrice и Credit должно быть то же самое, что и NetTotal.

Так что вместо того, чтобы иметь много Invoices с тем же самым Hash, У меня будет только один счет-фактура с этим хэшем, который имеет сумму значений выше.

Код уже удаляет дубликаты и суммирует значения, но почему-то я не знаю, как решить эту проблему.

Было бы здорово, если бы кто-то помог мне с решением этой проблемы, и мне также нужно сохранить "отредактированный" файл, чего не происходит, но моя главная проблема-избавиться от этой ошибки.

Что я уже пробовал:

//File
            const string FILE = "ccc.xml";
            static void Main(string[] args)
            {
                XDocument doc = XDocument.Load(FILE);
    
                List <XElement> originalInvoices = doc.Descendants("Invoice").ToList();
    
                var groups = originalInvoices.GroupBy(x => (string)x.Element("Hash")).ToList();
    
                var finalInvoices = groups.Select(x => new {
                    unit = x.Descendants("UnitPrice").Sum(z => (decimal)z),
                    credit = x.Descendants("CreditAmount").Sum(z => (decimal)z),
                    tax = x.Descendants("TaxPayable").Sum(z => (decimal)z),
                    net = x.Descendants("NetTotal").Sum(z => (decimal)z),
                    gross = x.Descendants("GrossTotal").Sum(z => (decimal)z),
                    first = x.First()
                }).ToList();
    
                foreach (var finalInvoice in finalInvoices)
                {
                    finalInvoice.first.Element("Line").SetElementValue("UnitPrice", finalInvoice.unit);
                    finalInvoice.first.Element("Line").SetElementValue("CreditAmount", finalInvoice.credit);
                    finalInvoice.first.Element("DocumentTotals").SetElementValue("TaxPayable", finalInvoice.tax);
                    finalInvoice.first.Element("DocumentTotals").SetElementValue("NetTotal", finalInvoice.net);
                    finalInvoice.first.Element("DocumentTotals").SetElementValue("GrossTotal", finalInvoice.gross);
                }
    
                doc.Element("SalesInvoices").ReplaceWith(new XElement("SalesInvoices", finalInvoices.Select(x => x.first)));
                Console.WriteLine(doc);
                Console.ReadKey();
    
            }
        }
    }

2 Ответов

Рейтинг:
1

#realJSOP

Узнайте, как использовать отладчик Visual Studio. Я не могу достаточно подчеркнуть это.

Поставить try/catch заблокируйте свой код и поставьте точку останова на одном из блоков. catch блокируйте фигурные скобки, чтобы отладчик останавливался при возникновении исключения. Хотите верьте, хотите нет, но он точно подскажет вам, в какой линии находится проблема, и вы сможете осмотреть различные объекты, используемые в ней, чтобы найти его. null один.

static Main(string[] args)
{
    try
    {
        // all of your code
    }
    catch (Exception ex)
    { // put a breakpoint here
    } // or here
}


Как новый разработчик, вы потратите больше времени на отладку кода, чем на его написание. Очень важно развивать достойные навыки отладки.


Рейтинг:
1

Maciej Los

Ваш xml-файл содержит Пространство имен[^]. Таким образом, чтобы иметь возможность получать данные из вашего файла, вы должны использовать имя пространства имен вместе с именем узла/элемента. Видеть:

string sFile = @"FullFileName.xml";
XDocument xDoc = XDocument.Load(sFile);
XNamespace n = xDoc.Root.Name.Namespace;
var result = xDoc.Descendants(n+"Invoice")
    .GroupBy(x=> x.Element(n+"Hash").Value)
    .ToList();


Это должно помочь вам избежать `An unhandled exception of type 'System.NullReferenceException' ошибка.

Удачи вам!