2012-03-06 2 views
1

Я хочу:списка XSLT преобразования и принять максимальные

  1. выбрать все атрибуты «Foo», которые являются строковыми значениями, и сохранять значения в списке.
  2. преобразуйте каждое значение атрибута «foo» в этот список, используя некоторую карту в моем xslt для числа.
  3. выберите максимальное значение списка и выведите его.

Так дал следующий XML:

<t> 
    <tag foo="A">apples</tag> 
    <tag foo="C">oranges</tag> 
    <tag foo="B">trees</tag> 
</t> 

И следующее отображение:

<xsl:variable name="myMap"> 
    <entry key="A">1</entry> 
    <entry key="B">2</entry> 
    <entry key="C">3</entry> 
</xsl:variable> 

Выходной сигнал будет:

<max>3</max> 

Другой вопрос, почему не может Я отступаю свой код? Я помещаю пробелы, но он не работает.

+0

Функция 'max()' недоступна в XSLT 1.0. Можете ли вы использовать решение XSLT 2.0? Если да, то почему этот вопрос помечен как «xslt-1.0»? –

+0

Я видел функцию max, но еще не использовал ее, потому что мне не удалось пройти шаг 2. Итак, если я не могу использовать функцию max в XSLT 1.0, это будет сложно:/ – Thirlan

ответ

3

I Этот стандарт XSLT 1.0 Преобразование (наиболее похожий ваш подход):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vrtfMap"> 
    <entry key="A" value="1"/> 
    <entry key="B" value="2"/> 
    <entry key="C" value="3"/> 
    <entry key="X" value="8"/> 
</xsl:variable> 

<xsl:variable name="vMap" select= 
    "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="@foo"> 
    <xsl:attribute name="foo"> 
    <xsl:value-of select="$vMap[@key = current()]/@value"/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на следующий документ XML (как вы не предоставили какой-либо):

<t foo="X"> 
    <a foo="A"> 
     <b foo="B"/> 
    </a> 
    <c foo="C"/> 
</t> 

дает желаемый, правильный результат:

<t foo="8"> 
    <a foo="1"> 
     <b foo="2"/> 
    </a> 
    <c foo="3"/> 
</t> 

Объяснение: Надлежащее использование XSLT current() функции.


II. XSLT 1.0 решение с использованием ключей для скорости

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kValFromKey" match="entry/@value" use="../@key"/> 

<xsl:variable name="vrtfMap"> 
    <entry key="A" value="1"/> 
    <entry key="B" value="2"/> 
    <entry key="C" value="3"/> 
    <entry key="X" value="8"/> 
</xsl:variable> 

<xsl:variable name="vMap" select= 
    "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="@foo"> 
    <xsl:variable name="vCur" select="."/> 

    <xsl:attribute name="foo"> 
    <xsl:for-each select="document('')"> 
    <xsl:value-of select="key('kValFromKey', $vCur)"/> 
    </xsl:for-each> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

Когда это преобразование применяется на том же самом документе XML (выше), то же правильный результат получается.

Объяснение:

  1. Использование <xsl:for-each select="document('')"> для установки текущего документа в таблице стилей, так что функция key() будет использовать индекс ключа, построенный для этого документа.

  2. Сохранение узла, совпавшего с шаблоном в переменной, так что мы можем использовать его внутри xsl:for-each - current() не может быть правильно использован здесь, потому что он получает текущий узел, на котором xsl:for-each работает.

UPDATE: ОП теперь уточнено в комментарии, что его самая большая проблема заключается в нахождении максимума.

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="vrtfMap"> 
     <entry key="A" value="1"/> 
     <entry key="B" value="2"/> 
     <entry key="C" value="3"/> 
    </xsl:variable> 

    <xsl:variable name="vMap" select= 
     "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/> 

    <xsl:template match="/"> 
    <xsl:variable name="vDoc" select="."/> 

     <xsl:variable name="vFoosMapped" 
      select="$vMap[@key = $vDoc/*/*/@foo]"/> 
     <max> 
     <xsl:value-of select= 
     "$vFoosMapped 
      [not($vFoosMapped/@value > @value)] 
       /@value 
     "/> 
     </max> 
    </xsl:template> 
</xsl:stylesheet> 

При введении этого XML-документ (тот, предоставленный OP отсутствует singlr верхний элемент):

<t> 
    <tag foo="A">apples</tag> 
    <tag foo="C">oranges</tag> 
    <tag foo="B">trees</tag> 
</t> 

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

<max>3</max> 

Примечание: более эффективный способ расчета тин максимум (или минимум - аналогичным образом) в XSLT 1.0, чтобы сделать это:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="vrtfMap"> 
     <entry key="A" value="1"/> 
     <entry key="B" value="2"/> 
     <entry key="C" value="3"/> 
    </xsl:variable> 

    <xsl:variable name="vMap" select= 
     "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/> 

    <xsl:template match="/"> 
    <xsl:variable name="vDoc" select="."/> 

     <xsl:variable name="vFoosMapped" 
      select="$vMap[@key = $vDoc/*/*/@foo]"/> 
     <max> 
     <xsl:for-each select="$vFoosMapped"> 
     <xsl:sort select="@value" data-type="number" order="descending"/> 

     <xsl:if test="position() = 1"> 
      <xsl:value-of select="@value"/> 
     </xsl:if> 
     </xsl:for-each> 
     </max> 
    </xsl:template> 
</xsl:stylesheet> 

Другой вопрос, почему я не могу отступы мой код? Я помещаю пробелы, но он не работает.

Это ошибка, которую они не смогли исправить в течение многих месяцев.

Возможно, вы используете IE. Если ваша версия 9, а затем выполните следующие действия:

  1. Нажмите F12.

  2. В появившемся окне нажмите на правой наиболее меню и выберите: «Режим документа: IE9 Standards»

Теперь вы должны быть в состоянии увидеть код с отступом.

+0

Прошу прощения за Dimitre , Я не был достаточно явным, заявив (1). Я не хочу искать и заменять то, что находится в xml. Я хочу найти максимальное значение в xml на основе некоторого отображения и выводить только одно значение. Я действительно должен был привести пример. Я исправил свой вопрос, чтобы привести пример. – Thirlan

+0

@ Тирлан: Да, я прокомментировал противоречие в вашем вопросе - вы сказали, что легко это сделали. –

+0

@Thirlan: По-прежнему существует противоречие: вы говорите: «* 1 и 2 легки. Я могу сделать выбор и использовать функцию max. 2 - это настоящая проблема, и кажется, что это разумно сильно». Я думал, что вы хотите сэкономить: ** 3 ** - настоящая проблема. Пожалуйста исправьте. –

Смежные вопросы