问题描述
我正在删除一个XML文件中的重复条目,并且代码正在删除它们,并将其汇总为只有每个发票的一个条目. 但是,当它到达末端时,它删除了以下3行:
<NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit>34422.86</TotalCredit>
因此,而不是让最终文件如下:
... <SourceDocuments> <SalesInvoices> <NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit>34422.86</TotalCredit> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
看起来像:
... <SourceDocuments> <SalesInvoices> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
我的代码是以下一个:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; namespace ConsoleApplication2 { class Program { //Ficheiro const string FILENAME = "ccc.xml"; static void Main(string[] args) { XDocument doc = XDocument.Load(FILENAME); XNamespace ns = doc.Root.Name.Namespace; List<XElement> originalInvoices = doc.Descendants(ns + "Invoice").ToList(); var groups = originalInvoices.GroupBy(x => (string)x.Element(ns + "Hash")).ToList(); var finalInvoices = groups.Select(x => new { unit = x.Descendants(ns + "UnitPrice").Sum(z => (decimal)z), credit = x.Descendants(ns + "CreditAmount").Sum(z => (decimal)z), tax = x.Descendants(ns + "TaxPayable").Sum(z => (decimal)z), net = x.Descendants(ns + "NetTotal").Sum(z => (decimal)z), gross = x.Descendants(ns + "GrossTotal").Sum(z => (decimal)z), first = x.First() }).ToList(); foreach (var finalInvoice in finalInvoices) { finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "UnitPrice", finalInvoice.unit); finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "CreditAmount", finalInvoice.credit); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "TaxPayable", finalInvoice.tax); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "NetTotal", finalInvoice.net); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "GrossTotal", finalInvoice.gross); } doc.Descendants(ns + "SalesInvoices").FirstOrDefault().ReplaceWith(new XElement(ns + "SalesInvoices", finalInvoices.Select(x => x.first))); doc.Descendants(ns + "SalesInvoices"). Console.WriteLine(doc); doc.Save("Root.xml"); Console.ReadKey(); } } }
您可以在此处看到我的XML文件的示例: pastebin link
有人可以帮助我解决这个问题,我该如何不删除这3行? 问题可能是在写文件的最后一行,但我不确定.
doc.Descendants(ns + "SalesInvoices").FirstOrDefault().ReplaceWith(new XElement(ns + "SalesInvoices", finalInvoices.Select(x => x.first)));
关于问题的小更新: 好吧,我真的认为问题出现在上面的行上,因为如果我更改例如SalesInvoices TotalCredit,那是消失的文件的最后一行,而不是:
... <SourceDocuments> <SalesInvoices> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
我得到了:
... <SourceDocuments> <SalesInvoices> <NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
标签之前有一个缺少的34422.86</TotalCredit> <Invoice>
并且在第一个关闭元素</Invoice>之后添加</TotalCredit>,您可以在此处进行测试:链接以测试测试代码
推荐答案
易于修复.只需添加丢失的3个元素:
foreach (var finalInvoice in finalInvoices) { finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "UnitPrice", finalInvoice.unit); finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "CreditAmount", finalInvoice.credit); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "TaxPayable", finalInvoice.tax); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "NetTotal", finalInvoice.net); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "GrossTotal", finalInvoice.gross); } XElement salesInvoices = doc.Descendants(ns + "SalesInvoices").FirstOrDefault(); XElement numberOfEntries = salesInvoices.Element(ns + "NumberOfEntries"); XElement totalDebit = salesInvoices.Element(ns + "TotalDebit"); XElement totalCredit = salesInvoices.Element(ns + "TotalCredit"); salesInvoices.ReplaceWith(new XElement(ns + "SalesInvoices", new object[] { numberOfEntries, totalDebit, totalCredit, finalInvoices.Select(x => x.first) }));
问题描述
I am removing the duplicated entries in one XML file, and the code is removing them and summing the values to have only one entry of each invoice. But when it reaches the end it removes 3 lines the following ones:
<NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit>34422.86</TotalCredit>
So instead of having the final file like:
... <SourceDocuments> <SalesInvoices> <NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit>34422.86</TotalCredit> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
It appears like:
... <SourceDocuments> <SalesInvoices> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
My code is the following one:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; namespace ConsoleApplication2 { class Program { //Ficheiro const string FILENAME = "ccc.xml"; static void Main(string[] args) { XDocument doc = XDocument.Load(FILENAME); XNamespace ns = doc.Root.Name.Namespace; List<XElement> originalInvoices = doc.Descendants(ns + "Invoice").ToList(); var groups = originalInvoices.GroupBy(x => (string)x.Element(ns + "Hash")).ToList(); var finalInvoices = groups.Select(x => new { unit = x.Descendants(ns + "UnitPrice").Sum(z => (decimal)z), credit = x.Descendants(ns + "CreditAmount").Sum(z => (decimal)z), tax = x.Descendants(ns + "TaxPayable").Sum(z => (decimal)z), net = x.Descendants(ns + "NetTotal").Sum(z => (decimal)z), gross = x.Descendants(ns + "GrossTotal").Sum(z => (decimal)z), first = x.First() }).ToList(); foreach (var finalInvoice in finalInvoices) { finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "UnitPrice", finalInvoice.unit); finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "CreditAmount", finalInvoice.credit); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "TaxPayable", finalInvoice.tax); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "NetTotal", finalInvoice.net); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "GrossTotal", finalInvoice.gross); } doc.Descendants(ns + "SalesInvoices").FirstOrDefault().ReplaceWith(new XElement(ns + "SalesInvoices", finalInvoices.Select(x => x.first))); doc.Descendants(ns + "SalesInvoices"). Console.WriteLine(doc); doc.Save("Root.xml"); Console.ReadKey(); } } }
And you can see a sample of my XML file here: Pastebin Link
Can someone help me with this, how can I make it to not remove those 3 lines? The problem is probably on the last line where it writes the file, but I'm not sure.
doc.Descendants(ns + "SalesInvoices").FirstOrDefault().ReplaceWith(new XElement(ns + "SalesInvoices", finalInvoices.Select(x => x.first)));
Small Update on the question: Well I really think that the problem is on the line above because if I change for example SalesInvoices with TotalCredit which is the last line of the ones that are disappearing the file still wrong but instead of:
... <SourceDocuments> <SalesInvoices> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
I'm getting:
... <SourceDocuments> <SalesInvoices> <NumberOfEntries>11972</NumberOfEntries> <TotalDebit>0</TotalDebit> <TotalCredit> <Invoice> <InvoiceNo>FS 006120180101/19959</InvoiceNo> ...
there is a missing 34422.86</TotalCredit> before tag <Invoice>
and it's adding the </TotalCredit> after the first closed element </Invoice> as you can test here: Link to test the code
推荐答案
Easy to fix. Just add the missing 3 elements :
foreach (var finalInvoice in finalInvoices) { finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "UnitPrice", finalInvoice.unit); finalInvoice.first.Element(ns + "Line").SetElementValue(ns + "CreditAmount", finalInvoice.credit); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "TaxPayable", finalInvoice.tax); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "NetTotal", finalInvoice.net); finalInvoice.first.Element(ns + "DocumentTotals").SetElementValue(ns + "GrossTotal", finalInvoice.gross); } XElement salesInvoices = doc.Descendants(ns + "SalesInvoices").FirstOrDefault(); XElement numberOfEntries = salesInvoices.Element(ns + "NumberOfEntries"); XElement totalDebit = salesInvoices.Element(ns + "TotalDebit"); XElement totalCredit = salesInvoices.Element(ns + "TotalCredit"); salesInvoices.ReplaceWith(new XElement(ns + "SalesInvoices", new object[] { numberOfEntries, totalDebit, totalCredit, finalInvoices.Select(x => x.first) }));