Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 读取分层XML并将其展平为对象列表?_C#_Xml - Fatal编程技术网

C# 读取分层XML并将其展平为对象列表?

C# 读取分层XML并将其展平为对象列表?,c#,xml,C#,Xml,我有一个XML文档,我想读取、展平并返回一个我称为PMRow的对象列表。对于XML中的每个编码行,都应该有一个对应的列表元素,发票的标题细节应该简单地重复。在这个转换中,许多XML元素将在Invoice和CodingRow级别被忽略。我已经开始编写下面的代码,但我无法概念化从那里开始: 不完整代码: public static List<PMRow> ParseToPMRows(FileInfo myFile) { var xDoc = XDocument.Load(myFi

我有一个XML文档,我想读取、展平并返回一个我称为PMRow的对象列表。对于XML中的每个编码行,都应该有一个对应的列表元素,发票的标题细节应该简单地重复。在这个转换中,许多XML元素将在Invoice和CodingRow级别被忽略。我已经开始编写下面的代码,但我无法概念化从那里开始:

不完整代码:

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 
}
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类型的两个对象:

阿基纳,180928003802901,2018年9月26日,700,700,05001990,01

AQUINC,180928003802901,2018年9月26日,700,700,02002390


这就是你要找的吗

    XElement invoice = xDoc.Root.Element("Invoice");

    List<PMRow> rows = invoice
        .Element("CodingRows")
        .Elements("CodingRow")
        .Select(codingRow => new PMRow
        {
            SupplierCode = invoice.Element("SupplierCode").Value,
            InvoiceNumber = invoice.Element("InvoiceNumber").Value,
            InvoiceDate = DateTime.Parse(invoice.Element("InvoiceDate").Value),
            GrossSum = decimal.Parse(invoice.Element("GrossSum").Value),
            NetSum = decimal.Parse(invoice.Element("NetSum").Value),
            TaxSum = decimal.Parse(invoice.Element("TaxSum").Value),
            CR_GrossSum = decimal.Parse(codingRow.Element("GrossSum").Value),
            AccountNumber = codingRow.Element("AccountCode").Value,
            DimCode1 = codingRow.Element("DimCode1").Value,
        })
        .ToList();
注:以上假设所有元素都存在且有效。如果情况并非如此,则需要为此添加适当的处理


Fiddle:

我通常发现,首先将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();

您可以从下面的代码中查看我的解决方案。我假设它们是一个文件中的多个发票,所以我必须使用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;
         }

我试试看。这看起来比我试图用查询语法概念化要简单得多。我不知道我能做什么。元素,然后。元素。我应该指定的。一个文件=一张发票。该代码适用于一张或多张发票。结果将是一样的。
        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;
         }