2011-02-27 107 views
5

,我有以下格式的XML整個的XDocument:排序基於子節點

<?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> 

我想排序基於他們的名字客戶名單,並在下面的格式返回文檔:

<?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> 

我正在使用c#和當前xmldocument。

謝謝

+0

我很混亂,因爲'xpath'標籤...如果你想選擇一個節點集,那麼XPath可能有正確的技術。如果您想正確排序節點集,則需要XPath引擎主機語言。如果要轉換XML樹,標準資源是XSLT。 – 2011-02-27 21:31:26

+0

我知道,我似乎無法解決我的問題。 – vondip 2011-02-27 21:38:09

+0

好問題,+1。查看我的答案,瞭解適用於'contactGrp'元素的任何級別嵌套的完整,簡短且容易的XSLT解決方案。 :) – 2011-02-27 23:48:18

回答

2

<?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

謝謝。我知道xslt是正確的方法,但無法讓xml對正確的級別進行排序。謝謝 – vondip 2011-02-28 04:26:11

4

如果你想有一個樣式表,並用它轉換然後將文檔你可以做這樣的事情

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

這種轉變

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

時所提供的XML文檔應用:

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

產生想要的,正確的結果:

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

請注意:正確的結果總是會產生 - 不管contactGrp元素的嵌套層次如何