Группировать и фильтровать данные XML с помощью XSL - PullRequest
1 голос
/ 27 января 2010

У меня есть следующий 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 ]

7 голосов
/ 27 января 2010

Сначала необходимо определить ключ для «группировки» всех элементов компании , которые имеют одну и ту же первую букву

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

Далее вы должны выполнить итерацию по всей компании элементов

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

Однако вы хотите обработать элемент 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>

Конечно, вы можете поместить это цикл для каждого, если хотите показать все выпадающие списки для всех возможных первых букв.

1 голос
/ 27 января 2010

Вот две таблицы стилей, первая для создания первой выборки:

<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>
1 голос
/ 27 января 2010

Вы должны взглянуть на метод Мюнхена для группировки в XSLT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...