Группировка и сбор вложенных объектов с помощью C# Linq - PullRequest
0 голосов
/ 11 апреля 2020

счастливого кодирования. Я могу группировать и суммировать с linq, но это немного по-другому. Я хочу сгруппировать элементы и собрать их один за другим. Я хочу группировать по TaxTypeCode и собирать значения TaxAmount. Извините, это такой длинный вопрос.

Мой xml

   <Note>
    <NoteLine>
        <cbc:ID>1</cbc:ID>
        <Quantity unitCode="C62">1.0000</Quantity>
        <TaxTotal>
            <cbc:TaxAmount currencyID="USD">201.00</cbc:TaxAmount>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">100.00</cbc:TaxAmount>
                <cbc:Percent>25.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>0003</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">50.00</cbc:TaxAmount>
                <cbc:Percent>10.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>9040</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">1.00</cbc:TaxAmount>
                <cbc:Percent>1.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>0001</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">50.00</cbc:TaxAmount>
                <cbc:Percent>10.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>8001</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
        </TaxTotal>
    </NoteLine>
    <NoteLine>
        <cbc:ID>2</cbc:ID>
        <Quantity unitCode="C62">1.0000</Quantity>
        <TaxTotal>
            <cbc:TaxAmount currencyID="USD">460.00</cbc:TaxAmount>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">1000.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">200.00</cbc:TaxAmount>
                <cbc:Percent>20.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>0003</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">1000.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">100.00</cbc:TaxAmount>
                <cbc:Percent>10.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>9040</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">1000.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">100.00</cbc:TaxAmount>
                <cbc:Percent>10.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>8001</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
            <TaxSubtotal>
                <cbc:TaxableAmount currencyID="USD">600.00</cbc:TaxableAmount>
                <cbc:TaxAmount currencyID="USD">60.00</cbc:TaxAmount>
                <cbc:Percent>10.00</cbc:Percent>
                <TaxCategory>
                    <TaxScheme>
                        <cbc:TaxTypeCode>8001</cbc:TaxTypeCode>
                    </TaxScheme>
                </TaxCategory>
            </TaxSubtotal>
        </TaxTotal>
    </NoteLine> 
</Note>

Тогда нам нужно что-то вроде этого. Итоговая такса, сумма налогообложения, сумма налога. Я думаю, что это возможно, но как я могу это сделать?

Результат, который я хочу

 <TaxTotal>
    <TaxAmount currencyID="USD">661.00</TaxAmount>
    <TaxSubtotal>
        <TaxableAmount currencyID="USD">1500.00</TaxableAmount>
        <TaxAmount currencyID="USD">300.00</TaxAmount>
        <Percent>25.00</Percent>
        <TaxCategory>
            <TaxScheme>
                <TaxTypeCode>0003</TaxTypeCode>
            </TaxScheme>
        </TaxCategory>
    </TaxSubtotal>
    ...
    ...
    ...
    ...
</TaxTotal>

У меня есть класс создания образца для сериализации xml.

using (StreamReader reader = new StreamReader(@"C:\Users\test.xml"))
 {
       XmlSerializer serializer = new XmlSerializer(typeof(Note));
       Note obj = (Note)serializer.Deserialize(reader);
 }

Но я все еще не могу этого сделать.

Ответы [ 2 ]

0 голосов
/ 11 апреля 2020

@ jdweng спасибо за все, ваши комментарии меня руководили.

Я решил это с вашей помощью.

XmlSerializer serializer = new XmlSerializer(typeof(Note));
                Note obj = (Note)serializer.Deserialize(reader);


                var Taxes = obj.NoteLine.SelectMany(rd => rd.TaxTotal.TaxSubtotal)
                .GroupBy(tt => tt.TaxCategory.TaxScheme.TaxTypeCode).Select(cl => new
                {
                    TaxableAmount = cl.Sum(x => x.TaxableAmount.Text),
                    TaxAmount = cl.Sum(x => x.TaxAmount.Text),
                    Tax = cl.First(),
                    cl.Key,
                });

                List<TaxSubtotal> TaxSubtotals = new List<TaxSubtotal>();

                int i = 1;
                foreach (var item in Taxes.ToList())
                {
                    TaxSubtotals.Add(new TaxSubtotal()
                    {
                        Percent = item.Tax.Percent,
                        TaxableAmount = new TaxableAmount()
                        {
                            CurrencyID = "USD",
                            Text = item.TaxableAmount
                        },
                        TaxAmount = new TaxAmount()
                        {
                            CurrencyID = "USD",
                            Text = item.TaxAmount
                        },
                        TaxCategory = new TaxCategory()
                        {
                            TaxScheme = new TaxScheme()
                            {
                                Name = item.Tax.TaxCategory.TaxScheme.Name,
                                TaxTypeCode = item.Tax.TaxCategory.TaxScheme.TaxTypeCode
                            },
                        },
                    });
                }
            }
0 голосов
/ 11 апреля 2020

Попробуйте следующее. Это возможно. Сохранены все пространства имен. Хитрость заключается в том, чтобы создать шаблон с помощью метода First (). :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            XElement note = doc.Descendants().Where(x => x.Name.LocalName == "Note").FirstOrDefault();
            XNamespace nsCbc = note.GetNamespaceOfPrefix("cbc");
            XNamespace ns = note.GetDefaultNamespace();

            foreach (XElement taxTotal in note.Descendants(ns + "TaxTotal"))
            {
                var groups = taxTotal.Elements(ns + "TaxSubtotal").GroupBy(x => (string)x.Descendants(nsCbc + "TaxTypeCode").First()).Select(x => new {
                    template = x.First(),
                    taxAmount = x.Descendants(nsCbc + "TaxableAmount").Sum(z => (decimal)z),
                    tax = x.Descendants(nsCbc + "TaxAmount").Sum(z => (decimal)z)
                }).ToList();

                foreach (var group in groups)
                {
                    group.template.SetElementValue(nsCbc + "TaxableAmount", group.taxAmount);
                    group.template.SetElementValue(nsCbc + "TaxAmount", group.tax);
                    group.template.SetElementValue(nsCbc + "Percent", 100 * (group.tax / group.taxAmount));

                }
                List<XElement> newSubtotals = groups.Select(x => new XElement(x.template)).ToList();
                taxTotal.Elements(ns + "TaxSubtotal").Remove();
                taxTotal.Add(newSubtotals);
            }


        }
    }
}

Он на выходе XML

<?xml version="1.0" encoding="utf-8"?>
<Note xmlns:cbc="abc">
  <NoteLine>
    <cbc:ID>1</cbc:ID>
    <Quantity unitCode="C62">1.0000</Quantity>
    <TaxTotal>
      <cbc:TaxAmount currencyID="USD">201.00</cbc:TaxAmount>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">100.00</cbc:TaxAmount>
        <cbc:Percent>20.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>0003</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">50.00</cbc:TaxAmount>
        <cbc:Percent>10.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>9040</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">1.00</cbc:TaxAmount>
        <cbc:Percent>0.200</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>0001</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">500.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">50.00</cbc:TaxAmount>
        <cbc:Percent>10.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>8001</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
    </TaxTotal>
  </NoteLine>
  <NoteLine>
    <cbc:ID>2</cbc:ID>
    <Quantity unitCode="C62">1.0000</Quantity>
    <TaxTotal>
      <cbc:TaxAmount currencyID="USD">460.00</cbc:TaxAmount>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">1000.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">200.00</cbc:TaxAmount>
        <cbc:Percent>20.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>0003</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">1000.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">100.00</cbc:TaxAmount>
        <cbc:Percent>10.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>9040</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
      <TaxSubtotal>
        <cbc:TaxableAmount currencyID="USD">1600.00</cbc:TaxableAmount>
        <cbc:TaxAmount currencyID="USD">160.00</cbc:TaxAmount>
        <cbc:Percent>10.0</cbc:Percent>
        <TaxCategory>
          <TaxScheme>
            <cbc:TaxTypeCode>8001</cbc:TaxTypeCode>
          </TaxScheme>
        </TaxCategory>
      </TaxSubtotal>
    </TaxTotal>
  </NoteLine>
</Note>
...