我解决了命名空间问题,但我仍然有错误消息。我认为问题在于将信息输入列表
IEnumerable<XElement> InvoiceLines = from e in Document.Root
.Element(P + "InvoiceLines")
.Elements(P + "InvoiceLine")
select new XElement("InvoiceLine",
new XAttribute("LineNumber", e.Element(P + "ID").Value),
new XAttribute("ProductName", e.Element(P + "Item").Attribute(P + "Description").Value),
new XAttribute("UnitPriceTaxInclusive", e.Element(P + "UnitPriceTaxInclusive").Value),
new XAttribute("Quantity", e.Element(P + "InvoicedQuantity").Value),
new XAttribute("UnitCode", e.Element(P + "InvoicedQuantity").Attribute(P + "@unitCode").Value));
然后我尝试使用此InvoiceLines保存文档,如下所示:
XDocument FinalDocument = new XDocument(
new XElement("Invoice",
new XAttribute("BuyerName", BuyerName),
new XAttribute("SellerName", SellerName),
new XAttribute("IssueDate", IssueDate),
new XAttribute("ID", InvoiceID),
new XElement("InvoiceLines", InvoiceLines)
));
FinalDocument.Save(name);
FinalDocument.Save(Console.Out);
错误告诉我问题出现在InvoiceLines中的“select new XElement ...”行中
答案 0 :(得分:2)
如果没有找到匹配的元素或属性,可以导致.Value
,而不是使用NullReferenceException
,我建议使用(string)
强制转换,只需生成null
找不到有效值,并且空合并运算符??
:
IEnumerable<XElement> InvoiceLines =
from e in Document.Root
.Element(P + "InvoiceLines")
.Elements(P + "InvoiceLine")
select new XElement("InvoiceLine",
new XAttribute("LineNumber", (string)e.Element(P + "ID") ?? ""),
new XAttribute("ProductName", (e.Element(P + "Item") != null) ? (string)e.Element(P + "Item").Attribute(P + "Description") ?? "" : ""),
new XAttribute("UnitPriceTaxInclusive", (string)e.Element(P + "UnitPriceTaxInclusive") ?? ""),
new XAttribute("Quantity", (string)e.Element(P + "InvoicedQuantity") ?? ""),
new XAttribute("UnitCode", (string)e.Element(P + "InvoicedQuantity").Attribute(P + "@unitCode") ?? ""));
答案 1 :(得分:1)
这行代码对底层数据有很多假设。例如,这个:
e.Element(P + "Item").Attribute(P + "Description").Value
该段代码假定:
e
保证包含与P + "Item"
P + "Description"
这些假设贯穿整个那条线。因此,如果遇到不符合这些假设的数据,.Element()
或.Attribute()
可能会返回null
,在这种情况下,下一个.
(例如{{1} }})会尝试取消引用.Value
值,从而导致该错误。
要添加一些空值检查,您可以将其分成多行代码或将其全部放入内联。任何一种方法的可读性和可维护性都取决于您。例如,使用此细分:
null
您可以像这样添加一些错误检查:
new XAttribute("LineNumber", e.Element(P + "ID").Value)
我可以看到那可能非常难以理解的地方。假设new XAttribute("LineNumber",
(e == null ? string.Empty :
(e.Element(P + "ID") == null ? string.Empty :
e.Element(P + "ID").Value)))
本身永远不会是e
,您可以取消第一次检查。但是你的其他部分仍然会进行一些嵌套检查。
要将其拆分,您必须循环使用值而不是使用单个LINQ语句。像这样的结构:
null
这不是 100%相同,因为它急切加载整个集合。所以你也可以把循环本身分成另一个方法,它返回var InvoiceLines = new List<XElement>();
foreach (var e in Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine"))
{
// build an XElement object from e and add it to the list
}
并使用IEnumerable<XElement>
来不必急于加载整个东西。这取决于你。
想想看,你的初始数据选择器也做出了假设:
yield return
您可能还希望在此处添加Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine")
检查,以防您收到与这些谓词不匹配的数据。
答案 2 :(得分:0)
文档中可能不存在您的某些元素或属性。例如:
e.Element(P + "ID").Value
如果没有元素P + "ID"
,则在访问NullReferenceException
引用的Value
属性时,上面的行会抛出null
。您可能需要执行类似
e.Element(P + "ID") ?? 0
其中0是您希望它拥有的默认值。或者你可以通过一个老式的for
循环和一些if
循环来实现这一点。