使用XSL对XML数据进行分组和过滤 [英] Group by and filter XML data with XSL

查看:140
本文介绍了使用XSL对XML数据进行分组和过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下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>


>

解决方案

首先,您需要定义一个键,将所有公司元素分组

 < xsl:key name =companyLettermatch =companyuse =substring(text(),1, 1)/> 

接下来,您将迭代所有公司元素

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

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

 < xsl:variable name =firstLetterselect =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/Transformversion =1.0> 
< xsl:key name =companyLettermatch =companyuse =substring(text(),1,1)/>
< xsl:template match =/ root>
< select id =colors>
< xsl:sort select =text()/>
< xsl:variable name =firstLetterselect =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>

当然,如果您想要显示所有下拉菜单,所有可能的第一个字母都会被打破。

I have the following XML code:

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

and I need to do two things with it:

  1. Build a html dropdown with the unique first letters found in the company nodes. Such as:

    <select id="colors">
        <option value="B">B</option>
        <option value="O">O</option>
        <option value="Y">Y</option>
    </select>
    

  2. Build a secondary dropdown, which lists all the companies starting with a specific letter. Such as:

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

Any help would be appreciated!

解决方案

First you need to define a key to 'group' all company elements together that share the same first letter

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

Next, you would iterate over all company elements

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

However, you only want to process a company element if it is the first occurence of that element for its first letter. You do this by looking up the first element in your key for the first letter, and seeing if it is the same. Element comparison is done using the generate-id() function

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

Putting this altogether gives

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

For the second drop-down, you can use a named template that gets passed a letter as a parameter. You can look up all elements for that letter using the same key as above.

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

To call the template, it is simply a case of passing the required parameter, for example

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

Of course, you could put this is an for-each loop if you wanted to show all drop-downs for all possible first-letters.

这篇关于使用XSL对XML数据进行分组和过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆