XSLT: получение максимального значения из производных значений из исходных узлов XML - PullRequest
3 голосов
/ 13 января 2011

У меня есть структура XML, как показано ниже

<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>

Существует отображение, доступное для этих категорий в поисковом XML, подобном этому

<Lookup>
<cat>Video</cat>
<mapping>1</mapping>
</Lookup>
<Lookup>
<cat>Audio</cat>
<mapping>2</mapping>
</Lookup>
<Lookup>
<cat>Hybrid</cat>
<mapping>3</mapping>
</Lookup>
</ValueSet>

Теперь я ищу решение XSLT, которое может вернуть мне значение Max в качестве вывода в результате преобразования без использования функции расширения набора узлов.

Вот мои тесты

Контрольный пример 1:

Ввод:

<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>

Ожидаемый результат 3

Контрольный пример 2:

Ввод:

<Categories>
<cat>Video</cat>
<cat>Hybrid</cat>
</Categories>

Ожидаемый результат 3

Контрольный пример 3:

Ввод:

<Categories>
<cat>Video</cat>
<cat>Audio</cat>
</Categories>

Ожидаемый результат 2

Контрольный пример 4:

Ввод:

<Categories>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>

Ожидаемый результат 3

Контрольный пример 5:

Ввод:

<Categories>
<cat>Video</cat>
</Categories>

Ожидаемый результат 1

Заранее спасибо.

Обновление из комментариев :

Поиск информации для меня не доступно для загрузки [с document() функция]. Мне нужно сделать for-each на категории вводят, а затем выводят значение поиска. После этого мне нужно чтобы получить максимум.

У меня есть расширение, доступное из xsl процессор двигателя, чтобы получить это в xslt как показано ниже:

<xsl:value-of select='xx:lookupValue("MappingXML","Category",.,"COL1")'/>

Эта функция возвращает строку. это функция не возвращает набор узлов. я пробовал с переменной, захватывая все производные значения после выполнения for-each, но для дальнейшей обработки эта переменная выводится (RTF), в XSLt 1.0, у меня нет дескриптора ни в одной функции-набора ()

Ответы [ 3 ]

2 голосов
/ 14 января 2011

Из комментария к OP :

У меня есть расширение, доступное от процессора xsl engine, чтобы получить его в xslt, как показано ниже: <xsl:value-of select='xx:lookupValue("MappingXML","Category",.,"COL1")'/> - satish

Это работает в XSLT 2.0 и должно работать в XSLT 1.0 (просто удалите <xsl:function> и используйте свою функцию расширения):

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xx="my:xx"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xx:lookup>
    <ValueSet>
        <Lookup>
            <cat>Video</cat>
            <mapping>1</mapping>
        </Lookup>
        <Lookup>
            <cat>Audio</cat>
            <mapping>2</mapping>
        </Lookup>
        <Lookup>
            <cat>Hybrid</cat>
            <mapping>3</mapping>
        </Lookup>
    </ValueSet>
 </xx:lookup>

 <xsl:variable name="vlookupDoc" select="document('')/*/xx:lookup"/>

    <xsl:template match="/*">
      <xsl:call-template name="getMax">
        <xsl:with-param name="pNodes" select="cat"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="getMax">
      <xsl:param name="pcurrMax" select="-9999999999"/>
      <xsl:param name="pNodes"/>

      <xsl:choose>
       <xsl:when test="not($pNodes)">
         <xsl:value-of select="$pcurrMax"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:variable name="vNewVal" select=
         "number(xx:lookupValue($vlookupDoc,$pNodes[1]))"/>
         <xsl:call-template name="getMax">
          <xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
          <xsl:with-param name="pcurrMax" select=
           "number(($pcurrMax >= $vNewVal))*$pcurrMax
           +
            number(($vNewVal > $pcurrMax))*$vNewVal"/>
         </xsl:call-template>
       </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    <xsl:function name="xx:lookupValue">
      <xsl:param name="pLookupDoc"/>
      <xsl:param name="pCat"/>

      <xsl:value-of select=
        "$pLookupDoc/*/*[cat=$pCat]/mapping"/>
    </xsl:function>
</xsl:stylesheet>

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

<Categories>
    <cat>Video</cat>
    <cat>Audio</cat>
    <cat>Hybrid</cat>
</Categories>

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

3

код преобразуется в XSLT 1.0 :

<xsl:stylesheet version="12.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xx="Your Namespace Here"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xx:lookup>
    <ValueSet>
        <Lookup>
            <cat>Video</cat>
            <mapping>1</mapping>
        </Lookup>
        <Lookup>
            <cat>Audio</cat>
            <mapping>2</mapping>
        </Lookup>
        <Lookup>
            <cat>Hybrid</cat>
            <mapping>3</mapping>
        </Lookup>
    </ValueSet>
 </xx:lookup>

 <!-- You probably don't need this and the above embedded XML -->
 <xsl:variable name="vlookupDoc" select="document('')/*/xx:lookup"/>

    <xsl:template match="/*">
      <xsl:call-template name="getMax">
        <xsl:with-param name="pNodes" select="cat"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="getMax">
      <xsl:param name="pcurrMax" select="-9999999999"/>
      <xsl:param name="pNodes"/>

      <xsl:choose>
       <xsl:when test="not($pNodes)">
         <xsl:value-of select="$pcurrMax"/>
       </xsl:when>
       <xsl:otherwise>
       <!-- Change the call of the ext. function as appr. -->
         <xsl:variable name="vNewVal" select=
         "number(xx:lookupValue($vlookupDoc,$pNodes[1]))"/>
         <xsl:call-template name="getMax">
          <xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
          <xsl:with-param name="pcurrMax" select=
           "($pcurrMax >= $vNewVal)*$pcurrMax
           +
            ($vNewVal > $pcurrMax)*$vNewVal"/>
         </xsl:call-template>
       </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
1 голос
/ 14 января 2011

Это классический алгоритм максимума для XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xx="extension-URI">
    <xsl:template match="/">
        <xsl:for-each select="Categories/cat">
            <xsl:sort select="xx:lookupValue('MappingXML',
                                             'Category',
                                             .,
                                             'COL1')"
                      data-type="number"
                      order="descending"/>
            <xsl:if test="position()=1">
                <xsl:value-of select="xx:lookupValue('MappingXML',
                                                     'Category',
                                                     .,
                                                     'COL1')"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Конечно, ваши ограничения и отображение заставляют это добавить один дополнительный вызов к функции расширения ... Если это дорого, вы должны пойти с рекурсивным узлом за узлом (или обходом). на следующей оси родного брата) решение типа @ Dimitre.

В XPath / XSLT 2.0 это проще:

max(Categories/cat/xx:lookupValue('MappingXML','Category',.,'COL1')
0 голосов
/ 13 января 2011
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

    <xsl:template match="/*">
        <xsl:variable name="docLookup" select="document('lookup_file.xml')/*/Lookup"/>
        <xsl:variable name="avElms" select="cat"/>
        <xsl:value-of select="$docLookup/mapping
                            [not(. &lt; ../../Lookup[cat = $avElms]/mapping)]/text()"/>
    </xsl:template>
</xsl:stylesheet>

Результаты:

<Categories>
    <cat>Video</cat>
    <cat>Audio</cat>
    <cat>Hybrid</cat>
</Categories>

Результат 3

<Categories>
    <cat>Video</cat>
    <cat>Hybrid</cat>
</Categories>

Результат 3

<Categories>
    <cat>Video</cat>
    <cat>Audio</cat>
</Categories>

Результат 2

<Categories>
    <cat>Audio</cat>
    <cat>Hybrid</cat>
</Categories>

Результат 3

<Categories>
    <cat>Video</cat>
</Categories>

Результат 1

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