用于从XML创建对象和更新其属性的更好代码
本文关键字:属性 更好 代码 更新 XML 创建对象 用于 | 更新日期: 2023-09-27 18:04:56
我有多个Invoice元素的XML输入。我从这些元素创建发票对象。根据invoice元素的位置,我们需要分配序列号,并从另一个元素StatusMsg中找到相应的消息。
我有以下c#代码在。net 4.0。它工作得很好,可读性也很好。在不牺牲readability
的情况下,是否有更好的performance
代码?
// Create a collection of invoice elements
var invoiceEntities = xDoc.Descendants("Invoice")
.Select(x => new Invoice
{
Vendor = x.Element("Vendor") == null ? String.Empty : x.Element("Vendor").Value.Trim(),
Amount = x.Element("Amount") == null ? String.Empty : x.Element("Amount").Value.Trim()
});
List<Invoice> invoices = invoiceEntities.ToList();
//Iterate all entities for finding corresponding message element and update the entity's Message
int count = 0;
foreach (Invoice entity in invoices)
{
count++;
//Dynamic XPath statement
string messagePath = @"Status/StatusMsg/StatusDetail/Sequence[text()=" + count.ToString() + "]/../Message";
var statusDetails = xDoc.XPathSelectElements(messagePath).FirstOrDefault();
if (statusDetails != null)
{
entity.Message = statusDetails.Value;
entity.Sequence = count;
}
}
实体
public class Invoice
{
public string Vendor { get; set; }
public string Amount { get; set; }
public string Message { get; set; }
public int Sequence { get; set; }
}
XML> XDocument xDoc = XDocument.Parse(@"
<Status>
<StatusMsg>
<StatusType>INVOICE</StatusType>
<StatusCode>READYPAY</StatusCode>
<StatusTimestamp>2013-03-19T21:20:54Z</StatusTimestamp>
<StatusDetail>
<Sequence test=""K""> 2 </Sequence>
<Message>STL MESSAGE </Message>
</StatusDetail>
<StatusDetail>
<Sequence test=""1""> 1 </Sequence>
<Message>AKP MESSAGE</Message>
</StatusDetail>
<StatusDetail>
<Sequence> 1 </Sequence>
<Message>CC</Message>
</StatusDetail>
</StatusMsg>
<Invoices>
<Invoice>
<Vendor>
AKP LLC
</Vendor>
<Amount>
100
</Amount>
</Invoice>
<Invoice>
<Vendor>
STL Inc
</Vendor>
<Amount>
20950
</Amount>
</Invoice>
</Invoices>
</Status>
");
引用:
- 生成c#目标代码并从xml文档中为其属性赋值
- 使用注释将LINQ转换为XSLT风格的XML树- Eric White
- XSLT或Linq to XML的优点
关于我唯一可以真正推荐的是将StatusDetail
节点存储在列表中,只需抓住它们的全部,然后您可以通过第二个linq语句引用列表来过滤序列。不过,这最终可能比简单地构建和重用XPath字符串要慢。
var Details = xDoc.Descendants("StatusDetail").ToList();
...
var statusDetail = Details.Where(a => a.Sequence == count).FirstOrDefault();
作为一个挑剔的开发点,通常建议在做这样奇怪的连接字符串时使用String.Format
…关于反向代码更高效的事情…
string messagePath = String.Format("Status/StatusMsg/StatusDetail/Sequence[text()={0}]/../Message", count);
另一个选项,您已经构建了一个匿名类型,没有理由不将count构建到Invoice选项中。这至少使您不必在循环中分别声明和维护count。
int count = 1;
var invoiceEntities = xDoc.Descendants("Invoice")
.Select(x => new Invoice
{
Vendor = x.Element("Vendor") == null ? String.Empty : x.Element("Vendor").Value.Trim(),
Amount = x.Element("Vendor") == null ? String.Empty : x.Element("Amount").Value.Trim(),
Index = count++
});//yes that works, I tested it because even I wasn't sure, but Index is correct and different for each element