2011-02-27 14 views
5

tengo un xml con el siguiente formato:sorting toda XDocument basan en subnodos

<?xml version="1.0" encoding="utf-8"?> 
<contactGrp name="People"> 
    <contactGrp name="Developers"> 
    <customer name="Mike" ></customer> 
    <customer name="Brad" ></customer> 
    <customer name="Smith" ></customer> 
    </contactGrp> 
    <contactGrp name="QA"> 
    <customer name="John" ></customer> 
    <customer name="abi" ></customer> 
    </contactGrp> 
</contactGrp> 

me gustaría ordenar la lista de clientes en función de sus nombres, y devolver el documento en el formato siguiente:

<?xml version="1.0" encoding="utf-8"?> 
<contactGrp name="People"> 
    <contactGrp name="Developers"> 
    <customer name="Brad" ></customer> 
    <customer name="Mike" ></customer> 
    <customer name="Smith" ></customer> 
    </contactGrp> 
    <contactGrp name="QA"> 
    <customer name="abi" ></customer> 
    <customer name="John" ></customer> 
    </contactGrp> 
</contactGrp> 

Estoy usando C# y actualmente xmldocument.

gracias

+0

Confundo porque la etiqueta 'xpath' ... Si quiere seleccionar un conjunto de nodos, XPath podría usar la tecnología correcta. Si desea ordenar correctamente un conjunto de nodos, necesitará el lenguaje de host del motor XPath. Bu, si quieres transformar un árbol XML, el recurso estándar es XSLT. –

+0

Lo sé, no puedo hacer que funcione para mi problema. – vondip

+0

Buena pregunta, +1. Vea mi respuesta para una solución XSLT completa, corta y fácil que funciona para cualquier nivel de anidación de los elementos 'contactGrp'. :) –

Respuesta

2

Si usted quiere tener una hoja de estilo y utilizarla para transformar el documento a continuación:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/contactGrp"> 
    <contactGrp name="Developers"> 
     <xsl:apply-templates select="contactGrp"/> 
    </contactGrp> 
    </xsl:template> 

    <xsl:template match="contactGrp/contactGrp"> 
    <contactGrp> 
     <xsl:attribute name="name"> 
     <xsl:value-of select="@name"/> 
     </xsl:attribute> 

     <xsl:for-each select="customer"> 
     <xsl:sort select="@name"/> 
     <xsl:copy-of select="."/> 
     </xsl:for-each> 

    </contactGrp> 
    </xsl:template> 

</xsl:stylesheet> 
+0

gracias. Sabía que xslt era la forma correcta de hacerlo, pero no pude obtener el xml para ordenar el nivel correcto. gracias – vondip

4

Se podría hacer algo como esto

var doc = XDocument.Load(/* ... */); 

foreach (var g in doc.Descendants("contactGrp")) 
{ 
    var customers = g.Elements("customer").ToList(); 
    customers.Remove(); 
    g.Add(customers.OrderBy(c => c.Attribute("name").Value)); 
} 
2

Esta transformación :

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="contactGrp"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"> 
    <xsl:sort select="@name"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica sobre el documento XML proporcionado:

<contactGrp name="People"> 
    <contactGrp name="Developers"> 
     <customer name="Mike" ></customer> 
     <customer name="Brad" ></customer> 
     <customer name="Smith" ></customer> 
    </contactGrp> 
    <contactGrp name="QA"> 
     <customer name="John" ></customer> 
     <customer name="abi" ></customer> 
    </contactGrp> 
</contactGrp> 

produce el, resultado correcto deseada:

<contactGrp name="People"> 
    <contactGrp name="Developers"> 
    <customer name="Brad" /> 
    <customer name="Mike" /> 
    <customer name="Smith" /> 
    </contactGrp> 
    <contactGrp name="QA"> 
    <customer name="abi" /> 
    <customer name="John" /> 
    </contactGrp> 
</contactGrp> 

hacer la nota: Los resultados correctos siempre se producen - independientemente del nivel de anidación de los elementos contactGrp