使用XSL分组并过滤XML数据

时间:2010-01-27 11:41:17

标签: xml xslt group-by

我有以下XML代码:

<root>
    <options>
        <companies>
            <company url="http://www.brown.com">Brown LLC</company>
            <company url="http://www.yellow.com">Yellow LLC</company>
            <company url="http://www.black.com">Black LLC</company>
            <company url="http://www.bourdeaux.com">Bourdeaux LLC</company>
            <company url="http://www.orange.com">Orange LLC</company>           
        </companies>
    </options>
</root>

我需要做两件事:

  1. 使用公司节点中找到的唯一首字母构建html下拉列表。如:

    <select id="colors">
        <option value="B">B</option>
        <option value="O">O</option>
        <option value="Y">Y</option>
    </select>
    
  2. 构建辅助下拉列表,其中列出了以特定字母开头的所有公司。如:

    <select id="companiesB">
        <option value="http://www.black.com">Black LLC</option>
        <option value="http://www.bordeaux.com">Bordeaux LLC</option>
        <option value="http://www.brown.com">Brown LLC</option>
    </select>
    
  3. 任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:7)

首先,您需要定义一个键,将所有公司元素“分组”在一起,共享相同的第一个字母

<xsl:key name="companyLetter" match="company" use="substring(text(), 1, 1)" />

接下来,您将遍历所有公司元素

<xsl:for-each select="options/companies/company">

但是,您只想处理公司元素,如果它是第一个字母的第一个元素出现。您可以通过在第一个字母的键中查找第一个元素来查看它是否相同。元素比较使用generate-id()函数

完成
<xsl:variable name="firstLetter" select="substring(text(), 1, 1)" />
<xsl:if test="generate-id(.) = generate-id(key('companyLetter', $firstLetter)[1])" >

完全放弃

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:key name="companyLetter" match="company" use="substring(text(), 1, 1)"/>
   <xsl:template match="/root">
      <select id="colors">
         <xsl:for-each select="options/companies/company">
            <xsl:sort select="text()"/>
            <xsl:variable name="firstLetter" select="substring(text(), 1, 1)"/>
            <xsl:if test="generate-id(.) = generate-id(key('companyLetter', $firstLetter)[1])">
               <option>
                  <xsl:attribute name="value">
                     <xsl:value-of select="$firstLetter"/>
                  </xsl:attribute>
                  <xsl:value-of select="$firstLetter"/>
               </option>
            </xsl:if>
         </xsl:for-each>
      </select>
   </xsl:template>
</xsl:stylesheet>

对于第二个下拉列表,您可以使用以字母作为参数传递的命名模板。您可以使用与上面相同的键查找该字母的所有元素。

<xsl:template name="Companies">
   <xsl:param name="firstLetter"/>
   <select>
      <xsl:attribute name="id">
         <xsl:value-of select="$firstLetter"/>
      </xsl:attribute>
      <xsl:for-each select="key('companyLetter', $firstLetter)">
         <xsl:sort select="text()"/>
         <option>
            <xsl:attribute name="value">
               <xsl:value-of select="@url"/>
            </xsl:attribute>
            <xsl:value-of select="text()"/>
         </option>
      </xsl:for-each>
   </select>
</xsl:template>

要调用模板,只需传递所需参数,例如

<xsl:call-template name="Companies">
   <xsl:with-param name="firstLetter">B</xsl:with-param>
</xsl:call-template>

当然,如果您想要显示所有可能的首字母的所有下拉列表,您可以将此设置为for-each循环。

答案 1 :(得分:1)

您应该查看Muenchian Method以获取XSLT中的分组。

答案 2 :(得分:1)

这是两个样式表,第一个用于产生第一个选择:

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

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

  <xsl:key name="k1" match="company" use="substring(., 1, 1)"/>

  <xsl:template match="companies">
    <select id="colors">
      <xsl:apply-templates select="company[generate-id() = generate-id(key('k1', substring(., 1, 1))[1])]">
        <xsl:sort select="substring(., 1, 1)" data-type="text"/>
      </xsl:apply-templates>
    </select>
  </xsl:template>

  <xsl:template match="company">
    <option value="{substring(., 1, 1)}">
      <xsl:value-of select="substring(., 1, 1)"/>
    </option>
  </xsl:template>

</xsl:stylesheet>

第二个用于产生第二个选择元素:

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

  <xsl:param name="c" select="'B'"/>

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

  <xsl:template match="companies">
    <select id="companies{$c}">
      <xsl:apply-templates select="company[substring(., 1, 1) = $c]">
        <xsl:sort select="." data-type="text"/>
      </xsl:apply-templates>
    </select>
  </xsl:template>

  <xsl:template match="company">
    <option value="{@url}"><xsl:value-of select="."/></option>
  </xsl:template>

</xsl:stylesheet>