如何在XSLT 1.0中进行多个分组

时间:2011-12-06 05:46:38

标签: xml xslt-1.0

我的XSLT低于单一分组,但是我需要为我的xml进行多次分组:

XSLT1.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>
  <xsl:variable name="linkURL" select="'/system/ASPX/Link.aspx?ID='"/>
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
      <xsl:if test="self::navigation">
        <node GroupTitle="{//@GroupTitle[1]}" GroupCode="{//@GroupCode[1]}" url="{$linkURL}{//@GroupID[1]}">
          <nodes>
            <xsl:apply-templates select="node()" mode="group"></xsl:apply-templates>
          </nodes>
        </node>        
      </xsl:if>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[normalize-space(@GroupCode) and not(*[not(normalize-space(@GroupCode))])]"/>

  <xsl:template match="node[normalize-space(@GroupCode)]" mode="group">
    <xsl:copy>    
      <xsl:apply-templates select="@*" mode="group"/>   
      <xsl:apply-templates select="node()" mode="group"/>      
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node" mode="group">     
    <xsl:apply-templates select="node()" mode="group"/>
  </xsl:template>

  <xsl:template match="*" mode="group"/>

  <xsl:template  match="@*" mode="group">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
  <!-- node attributes to be deleted have an empty template each -->
  <xsl:template match="@GroupTitle" mode="group"/>
  <xsl:template match="@GroupCode" mode="group"/>
  <xsl:template match="@GroupID" mode="group"/>
</xsl:stylesheet>

XML的一部分:

<?xml version="1.0" encoding="utf-16"?>
<navigation path="/english">
    <resources>
        <Copyright>© 2011 mysite. All Rights Reserved.</Copyright>
    </resources>
    <node title="Root" id="tcm:233-38288-4" url="/">
        <node title="030. Plan &amp;amp; Book" id="tcm:233-38446-4" url="/plan_book/plan_and_book.aspx" indexpage="tcm:233-192249-64" compTitle="mysite Online Booking and Planning" imageSrcOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" imageSrcOff="/Preview/mysiteglobal/english/images/plan_book_tcm233-343460.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/plan_book_active_tcm233-343462.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" accessKey="P" GroupTitle="Plan and Book" GroupCode="PB" GroupID="tcm:234-458296">
            <node title="010. Search for a Flight" id="tcm:233-38911-4" url="/IBE.aspx" linktype="ibe" compTitle="Make a Booking" linksection="IBE" accessKey="1"/>
        </node> 
        <node title="035. Business Rewards" id="tcm:233-58061-4" url="/business_rewards/business_rewards.aspx" indexpage="tcm:233-358352-64" compTitle="Business Rewards" imageSrcOn="/Preview/mysiteglobal/english/images/business_rewards_highlight_tcm233-324549.gif" imageSrcOff="/Preview/mysiteglobal/english/images/business_rewards_tcm233-324548.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/business_rewards_active_tcm233-324551.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/business_rewards_highlight_tcm233-324549.gif" authentication="sme-guest" GroupTitle="Skywards and Business Rewards" GroupCode="SB" GroupID="tcm:233-358296">
        </node> 
        <node title="040. Skywards" id="tcm:233-38448-4" url="/Skywards/skywards.aspx" indexpage="tcm:233-192262-64" compTitle="Skywards" imageSrcOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" imageSrcOff="/Preview/mysiteglobal/english/images/skywards_tcm233-343463.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/skywards_active_tcm233-343465.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" accessKey="S" GroupTitle="Skywards and Business Rewards" GroupCode="SB" GroupID="tcm:233-358296">
            <node title="080. The mysite High Street" id="tcm:233-59871-4" url="/Skywards/the_mysite_high_street/the_mysite_high_street.aspx" indexpage="tcm:233-346057-64" compTitle="The mysite High Street"/>
            <node title="090. Log In" id="tcm:233-92637-4" url="https://www.skywards.com/index.aspx" indexpage="tcm:233-636665-64" linktype="external" compTitle="Log In"/>
            <node title="100. Login" id="tcm:233-93287-4" url="/Skywards/skywardLogin/" GroupTitle="Skywards and Business Rewards" GroupCode="SB" GroupID="tcm:233-358296"/>
            <node title="110. Logout" id="tcm:233-93288-4" url="/Skywards/skywardLogout/" GroupTitle="Skywards and Business Rewards" GroupCode="SB" GroupID="tcm:233-358296"/>
        </node>
    </node>
</navigation>   

在上面的xml中你会发现有两种类型的 GroupCode =“PB” GroupCode =“SB”,上面的XSLT代码只进行了一次分组,但是xml中可以有很多GroupCode,根据我的分组将完成。对于上面的部分XML,我看下面的输出:

<?xml version="1.0" encoding="UTF-8"?>
<navigation path="/english">
    <resources>
        <Copyright>© 2011 mysite. All Rights Reserved.</Copyright>
    </resources>
    <node title="Root" id="tcm:233-38288-4" url="/">
        <node title="030. Plan &amp;amp; Book" id="tcm:233-38446-4" url="/plan_book/plan_and_book.aspx" indexpage="tcm:233-192249-64" compTitle="mysite Online Booking and Planning" imageSrcOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" imageSrcOff="/Preview/mysiteglobal/english/images/plan_book_tcm233-343460.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/plan_book_active_tcm233-343462.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" accessKey="P" GroupTitle="Plan and Book" GroupCode="PB" GroupID="tcm:234-458296">
            <node title="010. Search for a Flight" id="tcm:233-38911-4" url="/IBE.aspx" linktype="ibe" compTitle="Make a Booking" linksection="IBE" accessKey="1"/>
        </node>
        <node title="040. Skywards" id="tcm:233-38448-4" url="/Skywards/skywards.aspx" indexpage="tcm:233-192262-64" compTitle="Skywards" imageSrcOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" imageSrcOff="/Preview/mysiteglobal/english/images/skywards_tcm233-343463.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/skywards_active_tcm233-343465.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" accessKey="S" GroupTitle="Skywards and Business Rewards" GroupCode="SB" GroupID="tcm:233-358296">
            <node title="080. The mysite High Street" id="tcm:233-59871-4" url="/Skywards/the_mysite_high_street/the_mysite_high_street.aspx" indexpage="tcm:233-346057-64" compTitle="The mysite High Street"/>
            <node title="090. Log In" id="tcm:233-92637-4" url="https://www.skywards.com/index.aspx" indexpage="tcm:233-636665-64" linktype="external" compTitle="Log In"/>
        </node>
    </node>
    <node GroupTitle="Plan and Book" GroupCode="PB" url="/system/ASPX/Link.aspx?ID=tcm:234-458296">
        <nodes>
            <node title="030. Plan &amp;amp; Book" id="tcm:233-38446-4" url="/plan_book/plan_and_book.aspx" indexpage="tcm:233-192249-64" compTitle="mysite Online Booking and Planning" imageSrcOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" imageSrcOff="/Preview/mysiteglobal/english/images/plan_book_tcm233-343460.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/plan_book_active_tcm233-343462.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/plan_book_highlight_tcm233-343461.gif" accessKey="P"/>
        </nodes>    
    </node> 
    <node GroupTitle="Skywards and Business Rewards" GroupCode="SB" url="/system/ASPX/Link.aspx?ID=tcm:233-358296">
            <node title="035. Business Rewards" id="tcm:233-58061-4" url="/business_rewards/business_rewards.aspx" indexpage="tcm:233-358352-64" compTitle="Business Rewards" imageSrcOn="/Preview/mysiteglobal/english/images/business_rewards_highlight_tcm233-324549.gif" imageSrcOff="/Preview/mysiteglobal/english/images/business_rewards_tcm233-324548.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/business_rewards_active_tcm233-324551.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/business_rewards_highlight_tcm233-324549.gif" authentication="sme-guest">
            </node>
            <node title="040. Skywards" id="tcm:233-38448-4" url="/Skywards/skywards.aspx" indexpage="tcm:233-192262-64" compTitle="Skywards" imageSrcOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" imageSrcOff="/Preview/mysiteglobal/english/images/skywards_tcm233-343463.gif" imageSrcSelected="/Preview/mysiteglobal/english/images/skywards_active_tcm233-343465.gif" imageSrcSelectedOn="/Preview/mysiteglobal/english/images/skywards_highlight_tcm233-343464.gif" accessKey="S">
                <node title="100. Login" id="tcm:233-93287-4" url="/Skywards/skywardLogin/"/>
                <node title="110. Logout" id="tcm:233-93288-4" url="/Skywards/skywardLogout/"/>
            </node>
        </nodes>
    </node>
</navigation>

2 个答案:

答案 0 :(得分:0)

我使用以下更改修改了我的上述代码,似乎它对我有用,请建议是否需要进行任何更改。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>
  <xsl:variable name="linkURL" select="'/system/ASPX/Link.aspx?ID='"/>
  <xsl:key name="nodesByGroupsCode" match="*[node[not(@GroupCode)]]" use="@GroupCode" />
  <xsl:template match="*">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
      <xsl:if test="self::navigation">
      <xsl:for-each select="//node[generate-id() = generate-id(key('nodesByGroupsCode', @GroupCode)[1])]">       
        <node GroupTitle="{@GroupTitle}" GroupCode="{@GroupCode}" Url="{$linkURL}{@GroupID}">       
          <nodes>    
           <xsl:for-each select="key('nodesByGroupsCode', @GroupCode)"> 
          <xsl:copy> 
           <xsl:apply-templates select="@*" mode="group"/>         
             <xsl:apply-templates select="node()" mode="group"></xsl:apply-templates>       
           </xsl:copy>      
            </xsl:for-each>
          </nodes>            
        </node>    
        </xsl:for-each>    
      </xsl:if>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[normalize-space(@GroupCode) and not(*[not(normalize-space(@GroupCode))])]"/>

  <xsl:template match="node[normalize-space(@GroupCode)]" mode="group">    
    <xsl:copy>         
      <xsl:apply-templates select="@*" mode="group"/>      
    </xsl:copy>       
  </xsl:template>

  <xsl:template match="*" mode="group"/>

  <xsl:template  match="@*" mode="group">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

  <!-- node attributes to be deleted have an empty template each -->
  <xsl:template match="@GroupTitle" mode="group"/>
  <xsl:template match="@GroupCode" mode="group"/>
  <xsl:template match="@GroupID" mode="group"/>

</xsl:stylesheet>

答案 1 :(得分:0)

以上是上述问题的完整解决方案。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:variable name="linkURL" select="'/system/ASPX/Link.aspx?ID='"/>

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

     <!-- Key for Group Code attributes -->
    <xsl:key name="node" match="node" use="@GroupCode"/>

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

            <!-- use muenchian for that -->
            <xsl:if test="self::navigation">
                <xsl:for-each select="node/node[generate-id() = generate-id(key('node', @GroupCode)[1])]">
                    <xsl:variable name="this-group-code" select="@GroupCode"/>
                    <node GroupTitle="{@GroupTitle}" GroupCode="{@GroupCode}" Url="{$linkURL}{@GroupID}">
                        <nodes>
                            <!-- push out all the nodes that have this particular group code -->
                            <xsl:apply-templates select="ancestor::navigation/node/node[@GroupCode = $this-group-code]" mode="group"></xsl:apply-templates>
                        </nodes>
                    </node>
                </xsl:for-each>
            </xsl:if>
        </xsl:copy>
    </xsl:template>

    <!-- this template deletes all node that have a group code and no children that don't have a group code -->
    <xsl:template match="*[normalize-space(@GroupCode) and not(*[not(normalize-space(@GroupCode))])]"/>

    <!-- in mode group: copy all node that have a group code-->
    <xsl:template match="node[normalize-space(@GroupCode)]" mode="group">
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="group"/>
            <xsl:apply-templates select="node()" mode="group"/>
        </xsl:copy>            
    </xsl:template>

    <xsl:template match="node" mode="group">
        <xsl:apply-templates select="node()" mode="group"/>
    </xsl:template>

    <!-- group mode: remove all other elements (not specified in higher up templates) -->
    <xsl:template match="*" mode="group"/>

    <!-- in mode group, copy all attributes (except those that have a more specific template match with other instructions -->
    <xsl:template  match="@*" mode="group">
        <xsl:attribute name="{name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- node attributes to be deleted have an empty template each -->
    <xsl:template match="@GroupTitle" mode="group"/>
    <xsl:template match="@GroupCode" mode="group"/>
    <xsl:template match="@GroupID" mode="group"/>
</xsl:stylesheet>