我试图使用Linq对XElement的子级进行排序,然后用排序替换现有的子级。
首先,我创建XElement:
XElement WithLinq =
new XElement("Names",
from cust in Customers.AsEnumerable()
select
new XElement("Customer",
new XAttribute("ID", cust.ID),
new XElement("Name", cust.Name),
new XElement("Purchases",
from pur in cust.Purchases
select
new XElement("Purchase",
new XElement("Produkt",pur.Description),
new XAttribute("ID",pur.ID),
new XElement("Price",pur.Price),
new XComment("teraz daty"),
new XElement("Date",pur.Date), //Formatuje DateTime zgodnie z normami XMLa
new XElement("DataAleNieDoKonca",pur.Date.ToString(CultureInfo.InvariantCulture)))))
);然后对节点进行排序:
var NowaKolejnosc = WithLinq.Elements().Last().Elements().OrderBy(n => n.Name).ThenBy(n => n.Value);并替换它们:
WithLinq.Elements().Last().ReplaceNodes(NowaKolejnosc);但我得到了一个运行时异常: ArgumentException:'Co实现了ć元素IComparable。‘翻译:至少有一个对象必须实现IComparable。
我不明白是什么导致了异常,以及如何解决它。
发布于 2017-05-08 11:23:46
发生此错误是因为XElement.Name的类型为System.Xml.Linq.XName。XName不实现IComparable。
XName封装一个System.String值,并重写ToString以返回该System.String值。
由于System.String实现了IComparable,所以我们可以利用这些知识正确和成功地调用OrderBy。这具有所需的语义,因为在逻辑上,我们希望比较包装好的字符串。
WithLinq.Elements().Last().Elements().OrderBy(n => n.Name.ToString()).ThenBy(n => n.Value)当使用多个排序LINQ运算符时,我发现使用查询表达式语法更易读。
from element in WithLinq.Elements().Last().Elements()
orderby element.Name.ToString(), element.Value
select element发布于 2017-05-09 21:26:34
这是在阿伦·哈达德接受的回答的基础上发表的评论。
XName.LocalName建议:考虑使用代替 XName.ToString()**:**
直接使用element.Name.LocalName属性可能是合适的,前提是XML不使用名称空间,或者在特定操作中不需要XML中的名称空间。
在处理大型(> 1GB) XML文件时,我发现通过将XName.ToString()替换为XName.LocalName获得了适度的性能提高。
不过,这一变化在长达1小时的程序中节省了大约6分钟,这需要反复的排序和比较。在其他情况下,YMMV。
对于某些上下文,下面是通过参考源实现的区别
/// <summary>
/// Returns the expanded XML name in the format: {namespaceName}localName.
/// </summary>
public override string ToString() {
if (ns.NamespaceName.Length == 0) return localName;
return "{" + ns.NamespaceName + "}" + localName;
}/// <summary>
/// Gets the local (unqualified) part of the name.
/// </summary>
/// <seealso cref="XName.Namespace"/>
public string LocalName {
get { return localName; }
}https://stackoverflow.com/questions/43846208
复制相似问题