2010-08-12 23 views
12

Tüm öğeleri alfabetik olarak sıralamak istediğim bir XDocument var.Tüm öğeleri bir XDocument içinde sıralama

<Config> 
<Server> 
    <Id>svr1</Id> 
    <Routing> 
     <RoutingNodeName>route1</RoutingNodeName> 
     <Subscription> 
      <Id>1</Id> 
     </Subscription> 
     <RoutingParameters id="Routing1"> 
      <Timeout>7200</Timeout> 
     </RoutingParameters> 
    </Routing> 
    <Storage> 
      <Physical>HD1</Physical> 
    </Storage> 
</Server> 
<Applications> 
    <Services> 
     <Local></Local> 
    </Services> 
</Applications> 
</Config> 

Ben her düzeyde bu belgelerdeki unsurları sıralamak isteyen ediyorum şimdiye kadar ben şöyle sıralamak mümkün,: Burada yapının basitleştirilmiş versiyonu

private static XDocument Sort(XDocument file) 
{ 
    return new XDocument(
     new XElement(file.Root.Name, 
      from el in file.Root.Elements() 
      orderby el.Name.ToString() 
      select el)); 
} 

Hangi üretir:

<Config> 
<Applications> 
    <Services> 
    <Local></Local> 
    </Services> 
</Applications> 
<Server> 
    <Id>svr1</Id> 
    <Routing> 
    <RoutingNodeName>route1</RoutingNodeName> 
    <Subscription> 
     <Id>1</Id> 
    </Subscription> 
    <RoutingParameters id="Routing1"> 
     <Timeout>7200</Timeout> 
    </RoutingParameters> 
    </Routing> 
    <Storage> 
    <Physical>HD1</Physical> 
    </Storage> 
</Server> 
</Config> 
Ben (ideal bir özyinelemeli işlevi aracılığıyla) aynı şekilde çocukların bütün unsurları sıralamak mümkün istiyorum

. Bunu LINQ ile nasıl başarabileceğime dair herhangi bir fikrin var mı?

Herhangi bir fikir için teşekkürler.

cevap

18

Öğeleri sıralamak için zaten bir yönteminiz var. Sadece yinelemeli uygulama: Bu belgeden olmayan tüm eleman düğümleri (nitelikler, metin, yorumlar vs.) şeritler olduğunu

private static XElement Sort(XElement element) 
{ 
    return new XElement(element.Name, 
      from child in element.Elements() 
      orderby child.Name.ToString() 
      select Sort(child)); 
} 

private static XDocument Sort(XDocument file) 
{ 
    return new XDocument(Sort(file.Root)); 
} 

Not. Eğer sigara eleman düğümleri tutmak istiyorsanız


, onları buraya kopyalamak zorunda:

İşte
private static XElement Sort(XElement element) 
{ 
    return new XElement(element.Name, 
      element.Attributes(), 
      from child in element.Nodes() 
      where child.NodeType != XmlNodeType.Element 
      select child, 
      from child in element.Elements() 
      orderby child.Name.ToString() 
      select Sort(child)); 
} 

private static XDocument Sort(XDocument file) 
{ 
    return new XDocument(
      file.Declaration, 
      from child in file.Nodes() 
      where child.NodeType != XmlNodeType.Element 
      select child, 
      Sort(file.Root)); 
} 
+0

Teşekkür Bunu, hedeflediğim sonucu nitelik ve metinle elde etmek için kullanabildim. Şerefe. –

+0

Bu, düğümlerin nasıl sıralanacağını, ancak tüm değerlerden ve özniteliklerden nasıl kurtulduğunu göstermenin harika bir yoludur, OP'lerin sorusunu yanıtlayan bir yanıt değ[email protected], bu cevabı, herkese, aradığınız doğru cevabı nasıl aldığınızı gösterecek şekilde düzenlerseniz harika olurdu. –

+0

@ArvoBowen: Cevabımı güncelledim. – dtb

4
private static XElement Sort(XElement element) 
{ 
    XElement newElement = new XElement(element.Name, 
     from child in element.Elements() 
     orderby child.Name.ToString() 
     select Sort(child)); 
    if (element.HasAttributes) 
    { 
     foreach (XAttribute attrib in element.Attributes()) 
     { 
      newElement.SetAttributeValue(attrib.Name, attrib.Value); 
     } 
    } 
    return newElement; 
} 

private static XDocument Sort(XDocument file) 
{ 
    return new XDocument(Sort(file.Root)); 
} 

tür yaparken tüm özelliklerini içerecek güncelleştirilmiş örnektir.

Bu ileti bana çok yardımcı oldu, çünkü XML'i yeniden biçimlendirmek istemediğimden XSLT kullanarak bir XML sıralaması yapmak istemedim. Ben C# ve ASP.NET kullanarak bir XML sıralama gerçekleştirmek için basit bir çözüm için her yerinde aradım ve bu iş parçacığı bulduğumda çok memnun oldum. Herkese teşekkürler, bu tam olarak ihtiyacım olan şeyi yaptı.

~ Mat

+0

Bu OP'nin istediği şeyi başaramayacak. Bu tüm değerleri silecektir! –

-1

Bu uzantı yönteminin en iyi şekilde çalıştığını düşünüyorum.

public static class XmlLinq 
{ 
    public static void Sort(this XElement source, bool sortAttributes = true) 
    { 
    if (source == null) 
     throw new ArgumentNullException("source"); 

    if (sortAttributes) 
     source.SortAttributes(); 

    List<XElement> sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList(); 
    source.RemoveNodes(); 

    sortedChildren.ForEach(c => source.Add(c)); 
    sortedChildren.ForEach(c => c.Sort()); 
    } 

    public static void SortAttributes(this XElement source) 
    { 
    if (source == null) 
     throw new ArgumentNullException("source"); 

    List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList(); 
    sortedAttributes.ForEach(a => a.Remove()); 
    sortedAttributes.ForEach(a => source.Add(a)); 
    } 
} 
+0

Bu, takip etmem için harika bir temeldi, ancak tüm metin değerlerini veya özelliklerini korumaz. Bu yüzden birkaç değişiklikle yaptığım kendi yanıtımı eklemek zorunda kaldım. ;) –

10

BU YÖNTEM ... herkese teşekkürler GERÇEK BELGE UZANTI'yı VERMEZ VE nitelikleri korur VE METİN

Orada bu kapalı tabanlı birkaç farklı mesajlar ve kod buradan ve ile geldi DEĞERLER kim katkıda bulundu!

public static void Sort(this XElement source, bool bSortAttributes = true) 
{ 
    //Make sure there is a valid source 
    if (source == null) throw new ArgumentNullException("source"); 

    //Sort attributes if needed 
    if (bSortAttributes) 
    { 
     List<XAttribute> sortedAttributes = source.Attributes().OrderBy(a => a.ToString()).ToList(); 
     sortedAttributes.ForEach(a => a.Remove()); 
     sortedAttributes.ForEach(a => source.Add(a)); 
    } 

    //Sort the children IF any exist 
    List<XElement> sortedChildren = source.Elements().OrderBy(e => e.Name.ToString()).ToList(); 
    if (source.HasElements) 
    { 
     source.RemoveNodes(); 
     sortedChildren.ForEach(c => c.Sort(bSortAttributes)); 
     sortedChildren.ForEach(c => source.Add(c)); 
    } 
} 

belge uzantıyı kullanmak için aynı ad (değil aynı sınıfı) aşağıdakileri ekleyin içinde

... ...

//Load the xDoc 
XDocument xDoc = XDocument.Load("c:\test.xml"); 

//Sort the root element 
xDoc.Root.Sort(); 
+0

Burada en iyi cevap budur. Sadece işe yaradı. Teşekkürler! –

+0

Bir satırı değiştirmek için: Liste sıralanırChildren = source.Elements() OrderBy (elem => elem.Attributes ("Name"). Any()? Elem.Attributes ("Name"). First(). Value .ToString(): string.Empty) .ToList(); Ve edmx dosyalarını sıralamak için harika çalışıyor. Teşekkürler Arvo –