簡體   English   中英

如何添加ISortedEnumerable <XElement> 到XElement?

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

我正在嘗試使用Linq對XElement的子項進行排序,然后將現有的子項替換為sorted。

首先,我創建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:“無法實現IComparable元素。” 轉換:至少一個對象必須實現IComparable。

我不知道是什么導致異常以及如何解決它。

由於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

這是基於Aluan Haddad接受的答案的評論。

建議:考慮使用XName.LocalName代替XName.ToString()

如果XML不使用名稱空間特定操作不需要XML中的名稱空間,則直接使用element.Name.LocalName屬性可能是合適的。

當處理大型(> 1GB)XML文件時,通過將XName.ToString()換為XName.LocalName ,我發現性能有所提高。

有趣的是,在一個長達1小時的程序中,此更改節省了大約六分鍾的時間,需要重復進行排序和比較。 在其他情況下,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; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM