代码之家  ›  专栏  ›  技术社区  ›  devguy

按XSL分组并筛选XML数据

  •  1
  • devguy  · 技术社区  · 14 年前

    我有以下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 回复  |  直到 13 年前
        1
  •  7
  •   Tim C    14 年前

    首先,您需要定义一个“group”all的键 公司 共享相同第一个字母的元素

    <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”循环。

        2
  •  1
  •   Martin Honnen    14 年前

    以下是两个样式表,第一个用于生成第一个选择:

    <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>
    

    第二个用于生成第二个select元素:

    <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>
    
        3
  •  1
  •   JeremyP    13 年前

    你应该看看 Muenchian Method 用于在XSLT中分组。