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