如何在XSLT中使用密钥和应用模板

时间:2011-06-28 05:06:52

标签: xml xslt

我正在使用XSLT和XML,我的XML格式低于我。

<?xml version="1.0"?>
<offices>
  <resources resource="/include/xml/system_ek.xml" />
  <office id="217065">
    <city code="ABJ">Abidjan</city>
    <country code="CI">Cote D'Ivoire (Ivory Coast)</country>
    <region code="AF">Africa</region>
    <name>(Town office)</name>
    <countryTelephone>+225 2 025 6250</countryTelephone>
    <address>
      1st Floor, Escalier E<br />Immeuble Jeceda, Boulevard de la Republique<br />Le Plateau, Abidjan
    </address>
    <telephone>+225 2 025 6250</telephone>
    <fax>+225 2 025 6254</fax>
    <email>ekcotedivoire@test.com</email>
    <officeHours>Mon to Fri, 08:00 to 16:00</officeHours>
    <officeHours>Sat, 09:00 to 12:30</officeHours>
    <officeHours>Sun, Closed</officeHours>
    <description>test</description>
    <isCollectionOffice />
    <isFulfilmentOffice />
    <latitude>5.325053</latitude>
    <longitude>-4.019526</longitude>
  </office>
  <office id="217066">
    <city code="ACC">Accra</city>
    <country code="GH">Ghana</country>
    <region code="AF">Africa</region>
    <name>(Town office)</name>
    <countryTelephone>+233 2 121 3131</countryTelephone>
    <RefundRequestEmail>On-Line@test.com</RefundRequestEmail>
    <EmailReplyToAddress>On-Line@test.com</EmailReplyToAddress>
    <FareQuoteEnquiryEmail>test-On-Line@test.com</FareQuoteEnquiryEmail>
    <address>
      Ground floor, Meridian House<br />Ring Road Central, Accra
    </address>
    <telephone>+233 2 121 3131</telephone>
    <fax>+233 2 121 3158</fax>
    <email>test-On-Line@test.com</email>
    <officeHours>Mon to Fri, 09:45 to 17:00</officeHours>
    <officeHours>Sat, 09:00 to 13:00</officeHours>
    <officeHours>Sun, Closed</officeHours>
    <description>test</description>
    <isCollectionOffice />
    <isFulfilmentOffice />
    <latitude>5.573179</latitude>
    <longitude>-0.202158</longitude>
  </office>
  <office id="217067">
    <city code="ADD">Addis Ababa</city>
    <country code="ET">Ethiopia</country>
    <region code="AF">Africa</region>
    <name>test (Airport office)</name>
    <countryTelephone>+251 11 518 1818</countryTelephone>
    <address>
      Bole International Terminal
      <br />
      Office number - 2B
      <br />
      Addis Ababa
    </address>
    <telephone>+251 11 665 0434 / 35 / 06</telephone>
    <fax>+251 11 665 0437</fax>
    <email>ekethiopia@test.com</email>
    <officeHours>Daily, 09:00 to 21:00</officeHours>
    <description>Airport Office</description>
    <isCollectionOffice />
    <latitude>8.982919</latitude>
    <longitude>38.796329</longitude>
  </office>
</offices>

我在XSLT下面,它也使用分页,要求是它应该生成三列(“本地办公室”----“城市”-----“国家”)和所有细节在这个下面也是一样的。这是XSLT,当我试图制作列表时,我只是停止调用模板“Office”。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:tlink="urn:TridionLinking" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:utils="urn:XSLTExtensions" exclude-result-prefixes="xsl xlink tlink msxsl utils">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" />

  <!-- Translations are still loaded here because of XHTML content, research a way around that -->
  <xsl:key name="kOfficeByID" match="office" use="@id"/>
  <xsl:variable name="offices" select="/offices"/>
  <xsl:param name="publicationPath"/>
  <xsl:param name="pubURL"/>
  <xsl:param name="pageURL"/>
  <xsl:param name="country"/>
  <xsl:param name="city"/>
  <xsl:param name="sortby"/>
  <xsl:param name="order"/>


  <!-- Current date to determine articles to show based on published / unpublished dates -->
  <xsl:param name="currentDate"/>

  <!-- offset controls the starting position of the results to show -->
  <xsl:param name="offset">0</xsl:param>
  <!-- blockSize controls how many results to show on a single page -->
  <xsl:param name="blockSize" select="5" />

  <!-- Amount of page links to show by default -->
  <xsl:param name="pagesShown">15</xsl:param>

  <xsl:variable name="totalHits" >
    <xsl:choose>
      <xsl:when test="$city='' and $country=''">
        <xsl:value-of select="count(/offices/office)" />
      </xsl:when>
      <xsl:when test="$country!=''">
        <xsl:value-of select="count(/offices/office/country)" />
      </xsl:when>
      <xsl:when test="$city!=''">
        <xsl:value-of select="count(/offices/office/city)" />
      </xsl:when>
    </xsl:choose>
  </xsl:variable>

  <xsl:template name="calcStart">
    <xsl:choose>
      <xsl:when test="$offset = 0">1</xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="($offset * $blockSize) + 1"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="calcEnd">
    <xsl:choose>
      <xsl:when test="(($offset + 1) * $blockSize) > $totalHits">
        <xsl:value-of select="$totalHits"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="($offset + 1) * $blockSize"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="pageNavigation">
    <xsl:param name="pageCount"/>
    <xsl:param name="currPage"/>
    <xsl:param name="showPages">
      <xsl:choose>
        <xsl:when test="$pagesShown > $pageCount">
          <xsl:value-of select="$pageCount"/>
        </xsl:when>
        <xsl:when test="($pagesShown mod 2) = 0">
          <xsl:value-of select="$pagesShown"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$pagesShown + 1"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:param>
    <xsl:param name="currEntry" select="1"/>
    <xsl:param name="offset">
      <xsl:choose>
        <xsl:when test="($currPage &lt; $showPages) or ($pageCount = 1)">0</xsl:when>
        <xsl:when test="$currPage > ($pageCount - $showPages + 1)">
          <xsl:value-of select="$pageCount - $showPages"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$currPage - ($showPages div 2) - 1"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:param>

    <!-- Header Processing -->
    <xsl:if test="$currEntry = 1">
      <xsl:if test="($pageCount > $showPages) and ($currPage >= $showPages)">
        <li>... </li>
      </xsl:if>
    </xsl:if>

    <xsl:if test="not ($currEntry > $showPages)">
      <li>
        <xsl:choose>
          <xsl:when test="($currEntry + $offset) = $currPage">
            <strong class="thisPage">
              <xsl:value-of select="$currEntry + $offset"/>
            </strong>
          </xsl:when>
          <xsl:otherwise>
            <a href="{concat($pageURL,'?offset=',$currEntry + $offset - 1,'&amp;r=',$city,'&amp;c=',$country,'&amp;sortby=',$sortby,'&amp;order=',$order)}">
              <xsl:value-of select="$currEntry + $offset"/>
            </a>
          </xsl:otherwise>
        </xsl:choose>
      </li>

      <xsl:if test="not ($currEntry >=  $showPages)">
        <li class="separatorLine">|</li>
      </xsl:if>

      <xsl:call-template name="pageNavigation">
        <xsl:with-param name="pageCount" select="$pageCount"/>
        <xsl:with-param name="currPage" select="$currPage"/>
        <xsl:with-param name="showPages" select="$showPages"/>
        <xsl:with-param name="currEntry" select="$currEntry + 1"/>
        <xsl:with-param name="offset" select="$offset"/>
      </xsl:call-template>
    </xsl:if>

    <!-- Footer Processing -->
    <xsl:if test="$currEntry = 1">
      <xsl:if test="($pageCount > $showPages) and (($pageCount - $currPage + 1) >= $showPages)">
        <li> ...</li>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <xsl:template name="displayPageNavigation">
    <div class="continueBarPagination">
      <div class="continueBarLeft">
        <xsl:variable name="displayStart">
          <xsl:call-template name="calcStart"/>
        </xsl:variable>
        <xsl:variable name="displayEnd">
          <xsl:call-template name="calcEnd"/>
        </xsl:variable>
        <strong>
          <xsl:value-of select="concat($displayStart, '-', $displayEnd)"/>
        </strong>
      </div>
      <div class="continueBarRight">
        <ul class="paginationLinks">
          <!-- Show a back button when available -->
          <xsl:choose>
            <xsl:when test="$offset > 0">
              <li class="noBorder first">
                <a class="iconButtonBackBar" href="{$pageURL}?offset={$offset - 1}&amp;r={$country}&amp;c={$city}&amp;sortby={$sortby}&amp;order={$order}">
                  <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                </a>
              </li>
            </xsl:when>
            <xsl:otherwise>
              <li class="noBorder first">
                <span class="iconButtonBackBarOff">
                  <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                </span>
              </li>
            </xsl:otherwise>
          </xsl:choose>

          <!-- Output the page navigation links -->
          <xsl:call-template name="pageNavigation">
            <xsl:with-param name="pageCount">
              <xsl:choose>
                <xsl:when test="$blockSize >= $totalHits">1</xsl:when>
                <xsl:when test="($totalHits mod $blockSize) != 0">
                  <xsl:value-of select="ceiling($totalHits div $blockSize)"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$totalHits div $blockSize"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:with-param>
            <xsl:with-param name="currPage" select="$offset + 1"/>
          </xsl:call-template>

          <!-- Show a next button when available -->
          <xsl:choose>
            <xsl:when test="(($offset + 1) * $blockSize) >= $totalHits">
              <li class="last">
                <span class="iconButtonForwardBarOff">
                  <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                </span>
              </li>
            </xsl:when>
            <xsl:otherwise>
              <li class="last">
                <a class="iconButtonForwardBar" href="{$pageURL}?offset={$offset + 1}&amp;r={$country}&amp;c={$city}&amp;sortby={$sortby}&amp;order={$order}">
                  <xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
                </a>
              </li>
            </xsl:otherwise>
          </xsl:choose>
        </ul>
      </div>
      <div class="clearBoth">
        <xsl:comment/>
      </div>
    </div>
    <div class="spacer20">
      <xsl:comment/>
    </div>
  </xsl:template>

  <!-- root match -->
  <xsl:template match="/offices">
    <xsl:variable name="LinkUrl" select="concat($pageURL,'?offset=',$offset,'&amp;r=',$country,'&amp;c=',$city)"/>
    <input type="hidden" id="hdRegion" name="hdRegion" value="{$country}" />
    <div class="brownBarContainer">
      <div class="brownBar">
        <xsl:text>Local Offices</xsl:text>
      </div>
    </div>
    <table width="100%" cellspacing="0" cellpadding="0" border="0" class="displayTable">
      <tbody>
        <tr>
          <th scope="col">
            <xsl:choose>
              <xsl:when test="$sortby='d' or $sortby=''">
                <xsl:attribute name="class">first sortSelected</xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="class">first sortHover</xsl:attribute>
              </xsl:otherwise>
            </xsl:choose>
            <div class="thPadding">
              <xsl:element name="a">
                <xsl:choose>
                  <xsl:when test="($sortby='d' or $sortby='') and ($order='asc' or $order='')">
                    <xsl:attribute name="class">iconDownSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=d','&amp;order=desc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:when test="($sortby='d' or $sortby='') and ($order='desc' or $order='')">
                    <xsl:attribute name="class">iconUpSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=d','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=d','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:element>
              <xsl:text>Local Offices</xsl:text>
            </div>
          </th>
          <th scope="col">
            <xsl:choose>
              <xsl:when test="$sortby='r'">
                <xsl:attribute name="class">sortSelected</xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="class">sortHover</xsl:attribute>
              </xsl:otherwise>
            </xsl:choose>
            <div class="thPadding">
              <xsl:element name="a">
                <xsl:choose>
                  <xsl:when test="($sortby='r') and ($order='asc' or $order='')">
                    <xsl:attribute name="class">iconDownSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=r','&amp;order=desc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:when test="($sortby='r') and ($order='desc' or $order='')">
                    <xsl:attribute name="class">iconUpSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=r','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=r','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:element>
              <xsl:text>City</xsl:text>
            </div>
          </th>
          <th scope="col">
            <xsl:choose>
              <xsl:when test="$sortby='c'">
                <xsl:attribute name="class">sortSelected</xsl:attribute>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="class">sortHover</xsl:attribute>
              </xsl:otherwise>
            </xsl:choose>
            <div class="thPadding">
              <xsl:element name="a">
                <xsl:choose>
                  <xsl:when test="($sortby='c') and ($order='asc' or $order='')">
                    <xsl:attribute name="class">iconDownSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=c','&amp;order=desc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:when test="($sortby='c') and ($order='desc' or $order='')">
                    <xsl:attribute name="class">iconUpSortArrow</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=c','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
                    <xsl:attribute name="href">
                      <xsl:value-of select="concat($LinkUrl,'&amp;sortby=c','&amp;order=asc')" />
                    </xsl:attribute>
                  </xsl:otherwise>
                </xsl:choose>
              </xsl:element>
              <xsl:text>Country</xsl:text>
            </div>
          </th>
        </tr>
        <xsl:variable name="sortorder">
          <xsl:choose>
            <xsl:when test="$order='asc' or $order=''">ascending</xsl:when>
            <xsl:otherwise>descending</xsl:otherwise>
          </xsl:choose>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$city='' and $country=''">
            <xsl:choose>
              <xsl:when test="$sortby='d' or $sortby=''">
                <xsl:apply-templates select="office[@id]">
                  <xsl:sort select="$offices/office/name/." order="{$sortorder}" />
                </xsl:apply-templates>        
              </xsl:when>
              <xsl:when test="$sortby='r' or $sortby=''">
               <xsl:apply-templates select="office[@id]">
                  <xsl:sort select="$offices/office/city/." order="{$sortorder}" />
                </xsl:apply-templates>
              </xsl:when>
              <xsl:when test="$sortby='c' or $sortby=''">
                <xsl:apply-templates select="office[@id]">                
                  <xsl:sort select="$offices/office/country/." order="{$sortorder}" />
                </xsl:apply-templates>
              </xsl:when>
            </xsl:choose>
          </xsl:when>   
        </xsl:choose>        
      </tbody>
    </table>
    <div class="horRuleWhite">
      <hr/>
    </div>
    <xsl:call-template name="displayPageNavigation" />
  </xsl:template>

  <xsl:template match="office">
    <xsl:if test="(position() >= ($offset * $blockSize) + 1) and (position() &lt;= ($offset + 1) * $blockSize)">
      <xsl:variable name="cityId" select="@id"/>
      <xsl:variable name="url" select="$offices/destination[city/@id=$cityId]/@url"/>
      <xsl:variable name="vReverseURL">
        <xsl:call-template name="reverse">
          <xsl:with-param name="string" select="$url"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:variable name="vCountryURL">
        <xsl:call-template name="reverse">
          <xsl:with-param name="string" select="substring-after(substring-after($vReverseURL,'/'),'/')"/>
        </xsl:call-template>
        <xsl:text>/index.aspx</xsl:text>
      </xsl:variable>
      <xsl:variable name="vRegionURL">
        <xsl:call-template name="reverse">
          <xsl:with-param name="string" select="substring-after(substring-after(substring-after($vReverseURL,'/'),'/'),'/')"/>
        </xsl:call-template>
        <xsl:text>/index.aspx</xsl:text>
      </xsl:variable>
      <xsl:variable name="title">
        <xsl:choose>
          <xsl:when test="@title">
            <xsl:value-of select="@title"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$offices/office/name/." />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <tr>
        <td class="detail first">
          <a class="arrowSmallFront">
            <xsl:value-of select="$title"/>
          </a>
        </td>
        <td class="detail noLeftBorder">
          <a class="arrowSmallFront" href="{concat($pubURL, $vCountryURL)}">
            <xsl:value-of select="$offices/office/city/."/>
          </a>
        </td>
        <td class="detail noLeftBorder">
          <a class="arrowSmallFront" href="{concat($pubURL, $vRegionURL)}">
            <xsl:value-of select="$offices/office/country/."/>
          </a>
        </td>
      </tr>
    </xsl:if>
  </xsl:template>

  <xsl:template name="reverse">
    <xsl:param name="string" select="''"/>
    <xsl:if test="$string != ''">
      <xsl:call-template name="reverse">
        <xsl:with-param name="string" select="substring($string,2)"/>
      </xsl:call-template>
      <xsl:value-of select="substring($string,1,1)"/>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

在上面的XSLT中,我有一个名为xsl的模板:template match =“office”,如果你看到我正在使用“Key”。在下面我从上面的XSLT中获取的代码我试图使用apply-templates,但它不起作用,不考虑分页,我会照顾。

  <xsl:when test="$city='' and $country=''">
            <xsl:choose>
              <xsl:when test="$sortby='d' or $sortby=''">
                <xsl:apply-templates select="office[@id]">
                  <xsl:sort select="$offices/office/name/." order="{$sortorder}" />
                </xsl:apply-templates>        
              </xsl:when>
              <xsl:when test="$sortby='r' or $sortby=''">
               <xsl:apply-templates select="office[@id]">
                  <xsl:sort select="$offices/office/city/." order="{$sortorder}" />
                </xsl:apply-templates>
              </xsl:when>
              <xsl:when test="$sortby='c' or $sortby=''">
                <xsl:apply-templates select="office[@id]">                
                  <xsl:sort select="$offices/office/country/." order="{$sortorder}" />
                </xsl:apply-templates>
              </xsl:when>
            </xsl:choose>
      </xsl:when>   

1 个答案:

答案 0 :(得分:1)

由于您展示了巨大的代码墙,我无法理解您的意图。我可以解释一下在正常情况下如何使用xsl:key来应用模板。

如果您使用的密钥如下:

 <xsl:key name="kOfficeByID" match="office" use="@id"/>

您正在通过office收集@id个节点。如果您想使用密钥应用模板,请使用key()函数。

 <xsl:apply-templates select="key('kOfficeByID',@id)"/>

其中模板将应用于具有指示的office的所有@id节点。另一种方法(在众所周知的Meunchian方法中使用)是使用密钥将模板仅应用于具有给定密钥的单个办公室节点(即分组)。这可以通过以下方式实现:

 <xsl:apply-templates select="Office[
   generate-id()
    = generate-id( key('kOfficeByID',@id)[1] )]"/>