【发布时间】:2020-12-05 16:53:12
【问题描述】:
说明
我有一个表示 XML 文档的字符串,我想解析并创建以下类型的对象集合:
public class Invoice
{
public const string XmlName = "Invoice";
public int id { get; set; }
public string title { get; set; }
public DateTime timestamp { get; set; }
public bool paid { get; set; }
public IList<InvoiceItem> items { get; set; }
public Invoice() { this.items = List<InvoiceItem>(); }
public double getTotal()
{
if (items == null)
return 0;
double total = 0;
foreach (InvoiceItem item in this.items)
total += item.amount;
return total;
}
}
public class InvoiceItem
{
public const string XmlName = "InvoiceItem";
public string description { get; set; }
public double amount { get; set;}
}
用于测试目的的 XML 如下。我还没有创建架构,但本质上,它是Invoices 的列表,每个包含零个或多个InvoiceItems:
<?xml version="1.0" encoding="UTF-8"?>
<invoices>
<invoice id="1", title="Aug 2020", timestamp="16/08/2020 09:01:29 AM", paid="true">
<item desc="item 1 in invoice 1", amount="50"/>
<item desc="item 2 in invoice 1", amount="50"/>
</invoice>
<invoice id="2", title="Sep 2020", timestamp="16/09/2020 09:01:29 AM", paid="false">
<item desc="item in invoice 2", amount="100"/>
</invoice>
</invoices>
代码
以下是用于读取 XML 并生成所需输出的方法:
public IEnumerable<Invoice> readXML()
{
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.IgnoreWhitespace = true;
xmlReaderSettings.IgnoreComments = true;
xmlReaderSettings.IgnoreProcessingInstructions = true;
using (XmlReader reader = XmlReader.Create(new System.IO.StringReader(this._fileHandler.getXML()), xmlReaderSettings))
{
reader.MoveToContent(); // skip over the XML declaration, should move to the invoices start tag
reader.ReadStartElement("invoices"); // move to the next element, should be start tag for an invoice
while (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == Invoice.XmlName)
{
// hit an invoice start tag
// read it
Invoice invoice = new Invoice();
if (reader.MoveToAttribute("id"))
invoice.id = reader.ReadContentAsInt();
if (reader.MoveToAttribute("title"))
invoice.title = reader.ReadContentAsString();
if (reader.MoveToAttribute("timestamp"))
invoice.timestamp = DateTime.Parse(reader.ReadContentAsString());
if (reader.MoveToAttribute("paid"))
invoice.paid = reader.ReadContentAsBoolean();
reader.ReadStartElement("items"); // move to next element, should be items start tag
while (reader.NodeType == XmlNodeType.Element)
{
reader.Read();
InvoiceItem invoiceItem = new InvoiceItem();
if (reader.Name == InvoiceItem.XmlName)
{
if (reader.MoveToAttribute("desc"))
invoiceItem.description = reader.ReadContentAsString();
if (reader.MoveToAttribute("amount"))
invoiceItem.amount = reader.ReadContentAsDouble();
invoice.items.Add(invoiceItem);
}
else
{
throw new XmlException("Unexpected XML node: " + reader.Name);
}
}
yield return invoice;
}
else
{
throw new XmlException("Unexpected XML node: " + reader.Name);
}
}
}
}
在测试中,它会产生一个异常:
System.Xml.XmlException : Name cannot begin with the ',' character, hexadecimal value 0x2C. Line 3, position 17.
这是什么原因造成的?有关如何正确将此 XML 解析为所需对象列表的一些指导会很有帮助。
【问题讨论】: