读取分层XML并拼凑成对象列表?

时间:2018-10-22 21:10:14

标签: c# xml

我有一个XML文档,我想读取,展平并返回我称为PMRow的对象的List <>。对于XML中的每个CodingRow,应该有一个对应的List元素,并且发票的“标题”详细信息应该简单地重复。在此转换中,无论是在发票级别还是在CodingRow级别,许多XML元素都将被忽略。我已经开始编写下面的代码,而且我无法概念化从那里去的地方:

代码不完整:

public static List<PMRow> ParseToPMRows(FileInfo myFile)
{
    var xDoc = XDocument.Load(myFile.FullName);

    var query = from element in xDoc.Element("InvoiceDocument").Element("Invoice").Element("CodingRows").Elements("CodingRow")
                select 
}

目标类别:

public class PMRow
{
    public string SupplierCode { get; set; }
    public string InvoiceNumber { get; set; }
    public DateTime InvoiceDate { get; set; }
    public decimal GrossSum { get; set; }
    public decimal NetSum { get; set; }
    public decimal TaxSum { get; set; }
    public decimal CR_GrossSum { get; set; }
    public string AccountNumber { get; set; }
    public string DimCode1 { get; set; }
}

XML文档:

<InvoiceDocument>
<Method>Post</Method>
<Invoice>
    <GrossSum nil="False">700.000000</GrossSum>
    <InvoiceDate nil="False">2018-09-26</InvoiceDate>
    <InvoiceNumber nil="False">180928003802901</InvoiceNumber>
    <NetSum nil="False">700.000000</NetSum>
    <PaidSum nil="False">0.000000</PaidSum>
    <PaymentBlock nil="False">false</PaymentBlock>
    <PaymentDate nil="False">0001-01-01</PaymentDate>
    <SupplierCode nil="False">AQUINC</SupplierCode>
    <SupplierParentId nil="False"></SupplierParentId>
    <TaxCode nil="False"></TaxCode>
    <TaxPercent nil="False">0.000000</TaxPercent>
    <TaxPercent2 nil="False">0.000000</TaxPercent2>
    <TaxSum nil="False">0.000000</TaxSum>
    <OrderNumber nil="False"></OrderNumber>
    <OrderInCoding nil="False" />
    <CodingRows>
        <CodingRow>
            <GrossSum nil="False">500.000000</GrossSum>
            <InternalStatus nil="False">Loaded</InternalStatus>
            <AccountCode nil="False">1990</AccountCode>
            <AccountName nil="False">Gain on Non-Operating Asset</AccountName>
            <DimCode1 nil="False">01</DimCode1>
            <DimName1 nil="False">Operating/Unrestricted</DimName1>
            <MaterialGroup nil="False"></MaterialGroup>
            <FiscalYear nil="False"></FiscalYear>
            <DimCode3 nil="False">06</DimCode3>
            <DimName3 nil="False">Sports</DimName3>
            <DimCode4 nil="False">06500</DimCode4>
            <DimName4 nil="False">Personal Training</DimName4>
            <DimCode5 nil="False">6</DimCode5>
            <DimName5 nil="False">Minneapolis</DimName5>
            <DimCode6 nil="False"></DimCode6>
            <DimName6 nil="False"></DimName6>
        </CodingRow>
        <CodingRow>
            <GrossSum nil="False">200.000000</GrossSum>
            <InternalStatus nil="False">Loaded</InternalStatus>
            <AccountCode nil="False">2390</AccountCode>
            <AccountName nil="False">Gain on Non-Operating Asset</AccountName>
            <DimCode1 nil="False">02</DimCode1>
            <DimName1 nil="False">Operating/Unrestricted</DimName1>
            <MaterialGroup nil="False"></MaterialGroup>
            <FiscalYear nil="False"></FiscalYear>
            <DimCode3 nil="False">06</DimCode3>
            <DimName3 nil="False">Sports</DimName3>
            <DimCode4 nil="False">06500</DimCode4>
            <DimName4 nil="False">Personal Training</DimName4>
            <DimCode5 nil="False">6</DimCode5>
            <DimName5 nil="False">Minneapolis</DimName5>
            <DimCode6 nil="False"></DimCode6>
            <DimName6 nil="False"></DimName6>
        </CodingRow>
    </CodingRows>
    <InvoiceRows />
</Invoice>

概念化目标(列表中两个PMRow类型的对象):

  

AQUINC,180928003802901,2018/9/26,700,700,0,500,1990,01

     

AQUINC,180928003802901,2018/9/26,700,700,0,200,2390,02

3 个答案:

答案 0 :(得分:1)

这是您要寻找的吗?

=INDEX($A$1:$E$2, MOD(COLUMN(A:A)-1, 2)+1, (COLUMN(A:A)-1)/2+1)

注意:以上假设所有元素都将存在且有效。如果不是这种情况,则需要为此添加适当的处理。

提琴:https://dotnetfiddle.net/DjKcDg

答案 1 :(得分:0)

通常,我发现首先将XML序列化为类对象然后对序列化的对象进行迭代更方便。

您只需要

XmlSerializer serializer = new XmlSerializer(typeof(Invoice));

TextReader reader = new StringReader(source);

Invoice resultObj = (Invoice)serializer.Deserialize(reader);

var pmRows = resultObj.CodingRows.CodingRow.Select(item => new PMRow
{
     CR_GrossSum = Convert.ToDecimal(resultObj.GrossSum.Text),
     InvoiceDate = Convert.ToDateTime(resultObj.InvoiceDate.Text),
     InvoiceNumber = resultObj.InvoiceNumber.Text,
     SupplierCode = resultObj.SupplierCode.Text,
     NetSum = Convert.ToDecimal(resultObj.NetSum.Text),
     GrossSum = Convert.ToDecimal(resultObj.GrossSum.Text),
     TaxSum = Convert.ToDecimal(resultObj.TaxSum.Text),
     AccountNumber = item.AccountCode.Text,
     DimCode1 = item.DimCode1.Text
 }).ToList();

您可以从https://dotnetfiddle.net/jr11hB

查看我的解决方案

答案 2 :(得分:0)

请尝试以下代码。我假设它们在一个文件中是多个发票,所以我不得不使用SelectMany()返回平面列表

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

namespace ConsoleApplication75
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            ParseToPMRows(FILENAME);
        }
        public static List<PMRow> ParseToPMRows(string myFile)
        {
            XDocument xDoc = XDocument.Load(myFile);


            var tempResults = xDoc.Descendants("Invoice").Select(x => new {
                supplierCode = (string)x.Element("SupplierCode"),
                invoiceNumber = (string)x.Element("InvoiceNumber"),
                invoiceDate = (DateTime)x.Element("InvoiceDate"),
                grossSum = (decimal)x.Element("GrossSum"),
                netSum = (decimal)x.Element("NetSum"),
                taxSum = (decimal)x.Element("TaxSum"),
                codingRows = x.Descendants("CodingRow").Select(y => new {
                    crGrossSum = (decimal)y.Element("GrossSum"),
                    accounNumber = (string)y.Element("AccountCode"),
                    dimCode1 = (string)y.Element("DimCode1")
                }).ToList()
            }).ToList();

            List<PMRow> rows = tempResults.Select(x => x.codingRows.Select(y => new PMRow()
            {
                SupplierCode = x.supplierCode,
                InvoiceNumber = x.invoiceNumber,
                InvoiceDate = x.invoiceDate,
                GrossSum = x.grossSum,
                NetSum = x.netSum,
                TaxSum = x.taxSum,
                CR_GrossSum = y.crGrossSum,
                AccountNumber = y.accounNumber,
                DimCode1 = y.dimCode1
            })).SelectMany(x => x).ToList();

            return rows;
         }
    }
    public class PMRow
    {
        public string SupplierCode { get; set; }
        public string InvoiceNumber { get; set; }
        public DateTime InvoiceDate { get; set; }
        public decimal GrossSum { get; set; }
        public decimal NetSum { get; set; }
        public decimal TaxSum { get; set; }
        public decimal CR_GrossSum { get; set; }
        public string AccountNumber { get; set; }
        public string DimCode1 { get; set; }
    }
}

对于一张发票,您可以使用以下内容:

        public static List<PMRow> ParseToPMRows(string myFile)
        {
            XDocument xDoc = XDocument.Load(myFile);


            var tempResults = xDoc.Descendants("Invoice").Select(x => new {
                supplierCode = (string)x.Element("SupplierCode"),
                invoiceNumber = (string)x.Element("InvoiceNumber"),
                invoiceDate = (DateTime)x.Element("InvoiceDate"),
                grossSum = (decimal)x.Element("GrossSum"),
                netSum = (decimal)x.Element("NetSum"),
                taxSum = (decimal)x.Element("TaxSum"),
                codingRows = x.Descendants("CodingRow").Select(y => new {
                    crGrossSum = (decimal)y.Element("GrossSum"),
                    accounNumber = (string)y.Element("AccountCode"),
                    dimCode1 = (string)y.Element("DimCode1")
                }).ToList()
            }).FirstOrDefault();

            List<PMRow> rows = tempResults.codingRows.Select(x => new PMRow()
            {
                SupplierCode = tempResults.supplierCode,
                InvoiceNumber = tempResults.invoiceNumber,
                InvoiceDate = tempResults.invoiceDate,
                GrossSum = tempResults.grossSum,
                NetSum = tempResults.netSum,
                TaxSum = tempResults.taxSum,
                CR_GrossSum = x.crGrossSum,
                AccountNumber = x.accounNumber,
                DimCode1 = x.dimCode1
            }).ToList();

            return rows;
         }