简体   繁体   English

如何添加ISortedEnumerable <XElement> 到XElement?

[英]How can I add ISortedEnumerable<XElement> to XElement?

I'm trying to sort XElement's children using Linq and then replace existing children with sorted. 我正在尝试使用Linq对XElement的子项进行排序,然后将现有的子项替换为sorted。

First I create 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)))))    
                        );

Then I sort Nodes: 然后,我对节点进行排序:

var NowaKolejnosc = WithLinq.Elements().Last().Elements().OrderBy(n => n.Name).ThenBy(n => n.Value);

And replace them: 并替换它们:

WithLinq.Elements().Last().ReplaceNodes(NowaKolejnosc);

But I get a runtime exception: ArgumentException: 'Co najmniej jeden obiekt musi implementować element IComparable.' 但是我得到了一个运行时异常:ArgumentException:“无法实现IComparable元素。” Translation: At least one object must implement IComparable. 转换:至少一个对象必须实现IComparable。

I don't understand what is causing an exception and how to fix it. 我不知道是什么导致异常以及如何解决它。

The error is occurring because XElement.Name is of type System.Xml.Linq.XName . 由于XElement.Name的类型为System.Xml.Linq.XName,因此发生错误。 XName does not implement IComparable . XName不实现IComparable

XName wraps a System.String value and it overrides ToString to return that System.String value. XName包装一个System.String值,并覆盖ToString以返回该System.String值。

Since System.String implements IComparable we can leverage this knowledge to invoke OrderBy correctly and successfully. 由于System.String实现了IComparable我们可以利用此知识来正确,成功地调用OrderBy This has the desired semantics because, logically, we want to compare the wrapped strings. 这具有所需的语义,因为在逻辑上,我们要比较包装的字符串。

WithLinq.Elements().Last().Elements().OrderBy(n => n.Name.ToString()).ThenBy(n => n.Value)

When using multiple ordering LINQ operators, I find it much more readable to use the query expression syntax. 当使用多个排序LINQ运算符时,我发现使用查询表达式语法更具可读性。

from element in WithLinq.Elements().Last().Elements()
orderby element.Name.ToString(), element.Value
select element

This is a comment to build on the accepted answer by Aluan Haddad. 这是基于Aluan Haddad接受的答案的评论。

Suggestion: consider using XName.LocalName in place of XName.ToString() : 建议:考虑使用XName.LocalName代替XName.ToString()

Working directly with the element.Name.LocalName property may be suitable, provided that the XML does not use namespaces or the namespaces in the XML are not needed for a specific operation. 如果XML不使用名称空间特定操作不需要XML中的名称空间,则直接使用element.Name.LocalName属性可能是合适的。

When processing large (> 1GB) XML files, I've found moderate performance gains by swapping XName.ToString() for XName.LocalName . 当处理大型(> 1GB)XML文件时,通过将XName.ToString()换为XName.LocalName ,我发现性能有所提高。

Albeit anecdotally, this change saved around a half-dozen minutes on a 1 hour long program that required repeated sorts and comparisons. 有趣的是,在一个长达1小时的程序中,此更改节省了大约六分钟的时间,需要重复进行排序和比较。 In other contexts, YMMV. 在其他情况下,YMMV。

For some context, here are the differences via the reference source : 在某些情况下,以下是通过参考来源的区别:

/// <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; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM