2016-11-18 36 views
0

我有以下输入XML:如何进行分级XSL排序?

<?xml version="1.0" encoding="UTF-8"?> 
<soldiers> 
    <soldier> 
     <name>John</name> 
     <supervisor>Marcus</supervisor> 
    </soldier> 
    <soldier> 
     <name>Marcus</name> 
     <supervisor>Mike</supervisor> 
    </soldier> 
    <soldier> 
     <name>Frank</name> 
     <supervisor>Marcus</supervisor> 
    </soldier> 
    <soldier> 
     <name>Mike</name> 
     <supervisor>Anna</supervisor> 
    </soldier> 
</soldiers> 

现在我正在寻找一种方式排序此XML hierarchicaly基于主管标签。什么是最高效的方式来做到这一点?给出的例子的结果应该如下所示:

<?xml version="1.0" encoding="UTF-8"?> 
<soldiers> 
    <soldier> 
     <name>Mike</name> 
     <supervisor>Anna</supervisor> 
    </soldier> 
    <soldier> 
     <name>Marcus</name> 
     <supervisor>Mike</supervisor> 
    </soldier> 
    <soldier> 
     <name>John</name> 
     <supervisor>Marcus</supervisor> 
    </soldier> 
    <soldier> 
     <name>Frank</name> 
     <supervisor>Marcus</supervisor> 
    </soldier> 
</soldiers> 

因此,迈克没有在这里列出的主管,因此他位居榜首。马库斯的主管是迈克,因此他在迈克。约翰和弗兰克的主管是马库斯,因此他们处于最底层。

+0

您的处理器是否支持XSLT 2.0? –

+0

是的,它支持XSLT 1.0 – BenTreeser

+0

不是一个好的答案。请再次阅读该问题。 –

回答

1

可以使用key跟随引用:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:key name="ref" match="soldier" use="supervisor"/> 

    <xsl:template match="soldiers"> 
     <xsl:copy> 
      <xsl:apply-templates select="soldier[not(supervisor = ../soldier/name)]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="soldier"> 
     <xsl:copy-of select="."/> 
     <xsl:apply-templates select="key('ref', name)"/> 
    </xsl:template> 
</xsl:transform> 

基于@ michael.hor257k的评论,你也许更愿意

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
    xmlns:mf="http://example.com/mf" exclude-result-prefixes="mf"> 

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="ref" match="soldier" use="supervisor"/> 

    <xsl:variable name="main-root" select="/"/> 

    <xsl:function name="mf:refs" as="element(soldier)*"> 
     <xsl:param name="input" as="element(soldier)*"/> 
     <xsl:copy-of select="$input"/> 
     <xsl:sequence select="if (key('ref', $input/name, $main-root)) then mf:refs(key('ref', $input/name, $main-root)) else()"/> 
    </xsl:function> 

    <xsl:template match="soldiers"> 
     <xsl:copy> 
      <xsl:sequence select="mf:refs(soldier[not(supervisor = ../soldier/name)])"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:transform> 

它使用相同的密钥,但每个输出水平完全首先在递交到下一个级别之前。

相关问题