Ключ XSLT () поиск - PullRequest
       10

Ключ XSLT () поиск

4 голосов
/ 13 июня 2011

Я пробую образец справочных таблиц в XSLT и не могу заставить его работать

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" />
   <xsl:key name="classification-lookup" match="classification" use="id" />
   <xsl:variable name="classification-top" select="document('')/*/classifications" />
   <xsl:template match="BusinessListing">
      <listing>
         <id>
            <xsl:value-of select="id" />
         </id>
         <xsl:apply-templates select="$classification-top">
            <xsl:with-param name="curr-label" select="." />
         </xsl:apply-templates>
      </listing>
   </xsl:template>
   <xsl:template match="classifications">
      <xsl:param name="curr-label" />
      <category>
         <xsl:value-of select="key('classification-lookup', $curr-label/listingData/classifications/classificationId)/description" />
      </category>
   </xsl:template>
   <classifications>
      <classification>
         <id>7981</id>
         <description>Category1</description>
      </classification>
      <classification>
         <id>7982</id>
         <description>Category2</description>
      </classification>
      <classification>
         <id>7983</id>
         <description>Category3</description>
      </classification>
      <classification>
         <id>7984</id>
         <description>Category4</description>
      </classification>
   </classifications>
</xsl:stylesheet>

, а источник указан ниже.

<?xml version="1.0"?>
<BusinessListings>
<BusinessListing>
    <id>1593469</id>
    <listingData>
        <classifications>
            <classificationId>7982</classificationId>
            <classificationId>7983</classificationId>
        </classifications>
    </listingData>
</BusinessListing>
</BusinessListings>

В приведенном ниже результате категория пуста, но мне нужно, чтобы идентификатор классификации из источника сопоставлялся с идентификатором в теге классификации и сгенерированной категорией.

<?xml version="1.0" encoding="UTF-8"?>

<listing>
<id>1593469</id> -- Empty I need the Category2 and Category3 here
<category/>
</listing>

Я знаю, что, возможно, я не в курсе, но я только начал с XSLT и привел пример здесь http://www.ibm.com/developerworks/xml/library/x-xsltip.html. Спасибо за помощь.

1 Ответ

4 голосов
/ 13 июня 2011

Ваша таблица стилей XSLT содержит ошибку - в соответствии с spec , любым дочерним элементом xsl:stylesheet (он же элемент верхнего уровня) ) должно быть в ненулевом пространстве имен:

"* Кроме того, таблица стилей xsl: элемент может содержать любой элемент не из пространства имен XSLT, при условии, что расширенное имя элемента имеет ненулевой URI пространства имен. «

Если процессор XSLT, который вы используете, не вызывает ошибку, значит, он несовместим и содержит ошибки и не должен использоваться. Найдите и используйте совместимый XSLT-процессор (я использую .NET XslCompiledTransform, Saxon 6.5.5, ... и т. Д.).

Есть и другие ошибки.

Решение

  1. Определите новое пространство имен с префиксом (скажем) "x:":

  2. Измените встроенный <classifications> на <x:classifications> - теперь это соответствует спецификации.

  3. Вносите дополнительные изменения в код, пока не получите это преобразование:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="my:x" exclude-result-prefixes="x">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:key name="classification-lookup" match="classification"
             use="id" />
    
        <xsl:template match="BusinessListing">
            <listing>
                <id>
                    <xsl:value-of select="id" />
                </id>
                <xsl:apply-templates/>
            </listing>
        </xsl:template>
    
        <xsl:template match="classificationId">
         <xsl:variable name="vCur" select="."/>
            <xsl:for-each select="document('')">
             <category>
                <xsl:value-of select=
                "key('classification-lookup',$vCur)/description" />
             </category>
            </xsl:for-each>
        </xsl:template>
    
     <xsl:template match="text()"/> 
    
     <x:classifications>
        <classification>
            <id>7981</id>
            <description>Category1</description>
        </classification>
        <classification>
            <id>7982</id>
            <description>Category2</description>
        </classification>
        <classification>
            <id>7983</id>
            <description>Category3</description>
        </classification>
        <classification>
            <id>7984</id>
            <description>Category4</description>
        </classification>
     </x:classifications>
    </xsl:stylesheet>
    

    0,4. В приведенном выше коде обратите внимание на строку: <xsl:for-each select="document('')">.

Цель этого - сделать таблицу стилей текущим документом. Функция key() работает только с текущим документом, и если вы хотите, чтобы внедренные элементы classification были проиндексированы и использованы, вы должны изменить текущий документ (обычно таким образом). В XSLT 2.0 функция key() допускает третий аргумент, который является узлом из документа, индекс которого должен использоваться.

Когда это преобразование применяется к предоставленному документу XML:

    <BusinessListings>
        <BusinessListing>
            <id>1593469</id>
            <listingData>
                <classifications>
                    <classificationId>7982</classificationId>
                    <classificationId>7983</classificationId>
                </classifications>
            </listingData>
        </BusinessListing>
    </BusinessListings>

желаемый, правильный результат получается:

<listing>
   <id>1593469</id>
   <category>Category2</category>
   <category>Category3</category>
</listing>
...