문제

XSLT available is 1.0.

The XML and XSLT below is for building a dropdown navigation menu for nested categories. The level of categories may vary.

Sample XML:

<data>
  <categories-nav>
     <section id="11" handle="categories-1">Categories 1</section>
     <entry id="65">
       <name handle="air-rifles">Air Rifles</name>
       <subcategories field-id="50" subsection-id="12" items="2">
         <item id="66" quantity="1">
           <name handle="rifles">Rifles</name>
           <active>Yes</active>
           <subcategories field-id="57" subsection-id="13" items="2">
             <item id="67" quantity="1">
               <name handle="b2-series">B2 Series</name>
               <active>Yes</active>
             </item>
             <item id="112" quantity="1">
               <name handle="junior-supergrade">Junior Supergrade</name>
               <active>Yes</active>
             </item>
           </subcategories>
         </item>
         <item id="111" quantity="1">
           <name handle="accessories">Accessories</name>
           <active>Yes</active>
           <subcategories field-id="57" subsection-id="13" items="0" />
         </item>
       </subcategories>
     </entry>
     <entry id="118">
       <name handle="pistols">Pistols</name>
     </entry>
     <entry id="58">
       <name handle="bb-softair-guns">BB Softair Guns</name>
     </entry>
  </categories-nav>
</data>

My current XSLT:

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

<xsl:template name="categories-nav-entries" mode="navigation">
    <li class="{name/@handle}-{@id}">
        <a href="/cat/{@id}/{name/@handle}/"><xsl:value-of select="name"/></a>
        <xsl:apply-templates select="subcategories" mode="navigation"/>
    </li>
</xsl:template>

<!-- level 1 -->

<xsl:template match="/data/categories-nav" mode="navigation">
    <ul>
        <xsl:apply-templates select="entry" mode="navigation"/>
    </ul>
</xsl:template>

<xsl:template match="/data/categories-nav/entry" mode="navigation">
    <xsl:call-template name="categories-nav-entries" mode="navigation"/>
</xsl:template>

<!-- level 2 -->

<xsl:template match="/data/categories-nav/entry/subcategories" mode="navigation">
    <ul>
        <xsl:apply-templates select="item" mode="navigation"/>
    </ul>
</xsl:template>

<xsl:template match="/data/categories-nav/entry/subcategories/item" mode="navigation">
    <xsl:call-template name="categories-nav-entries" mode="navigation"/>
</xsl:template>

<!-- level 3 -->

<xsl:template match="/data/categories-nav/entry/subcategories/item/subcategories" mode="navigation">
    <ul>
        <xsl:apply-templates select="item" mode="navigation"/>
    </ul>
</xsl:template>

<xsl:template match="/data/categories-nav/entry/subcategories/item/subcategories/item" mode="navigation">
    <xsl:call-template name="categories-nav-entries" mode="navigation"/>
</xsl:template>

</xsl:stylesheet>

The only difference between the matches for the three different levels is repeated subcategories and item nodes.

I've successfully got the lis in their own named template, but is there a way I can avoid matching the three levels separately?

Also, it seems that because I'm using a mode on the initial match, I also have to use that mode on all subsequent matches - is that correct?

Edit: here's what I came up with after using relative paths as @michael's answer:

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

<xsl:template name="categories-nav-list">
    <li class="{name/@handle}">
        <a href="/cat/{@id}/{name/@handle}/"><xsl:value-of select="name"/></a>
        <xsl:apply-templates select="subcategories[@items > 0]"/>
    </li>
</xsl:template>

<xsl:template match="categories-nav">
    <ul>
        <xsl:apply-templates select="entry"/>
    </ul>
</xsl:template>

<xsl:template match="categories-nav/entry">
    <xsl:call-template name="categories-nav-list"/>
</xsl:template>

<xsl:template match="categories-nav//subcategories[item/active='Yes']">
    <ul>
        <xsl:apply-templates select="item"/>
    </ul>
</xsl:template>

<xsl:template match="categories-nav//subcategories/item[active='Yes']" priority="1">
    <xsl:call-template name="categories-nav-list"/>
</xsl:template>

<xsl:template match="categories-nav//subcategories/item" priority="0"/>

</xsl:stylesheet>
도움이 되었습니까?

해결책

You don't need to put absolute paths in each @match attribute.

Why not something like this:

<xsl:template match="subcategories">
  <ul>
    <xsl:apply-templates select="item"/>
  </ul>
</xsl:template>

<xsl:template match="item">
  <xsl:call-template name="categories-nav-entries"/>
</xsl:template>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top