Преобразование XML в строку с помощью XSLT

Нужно преобразовать XML в строку

Входной XML:

<Texts>
<text>123</text>
<text>456</text>
<text>789</text>
</Texts>

Выходная строка

T1=123&T2=456&T3=789

Я использую следующий XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
        <xsl:for-each select="Texts">
            <xsl:apply-templates mode="concat" select="text" />
        </xsl:for-each>
</xsl:template>

<xsl:template match="text" mode="concat">
    <xsl:variable name="position" select="position()"/>
    <xsl:if test="position() = 1">
        <xsl:text>P($position)=</xsl:text>
    </xsl:if>
    <xsl:value-of select="." />
    <xsl:if test="position() = last()">
        <xsl:text></xsl:text>
    </xsl:if>
    <xsl:if test="position() = last()"> 
    <xsl:text>&amp;P$position=</xsl:text>
    </xsl:if>
</xsl:template> 

</xsl:stylesheet>

Дайте мне знать, что не так. Текст элементов в XML может быть любым числом


person mnvbrtn    schedule 16.10.2013    source источник
comment
Будет намного проще, если вы сообщите нам, что случилось! :P Какой результат вы получаете?   -  person James Webster    schedule 16.10.2013
comment
Это результат, который я получил: P($position)=123456789&P$position=   -  person mnvbrtn    schedule 16.10.2013


Ответы (4)


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="Texts/text" />
  </xsl:template>

  <xsl:template match="text">
    <xsl:value-of select="concat('P', position(), '=', .)" />
    <xsl:if test="position() &lt; last()">&amp;</xsl:if>
  </xsl:template> 

</xsl:stylesheet>

выходы

P1=123&P2=456&P3=789

Обратите внимание, что на самом деле вы должны использовать кодировку URL для значений каждого <text>, но это не встроено в XSLT 1.0 (но в 2.0 есть функция для этого).

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

person Tomalak    schedule 16.10.2013
comment
Что бы это ни стоило, в EXSLT есть функция str:encode-uri, которую некоторые XSLT 1.0 поддержка процессоров. - person nwellnhof; 16.10.2013

Иногда проще использовать xsl:for-each:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:for-each select="Texts/text">
            <xsl:if test="position() != 1">&amp;</xsl:if>T<xsl:value-of select="position()" />=<xsl:value-of select="." />
        </xsl:for-each> 
    </xsl:template>
</xsl:stylesheet>
person Rubens Farias    schedule 16.10.2013
comment
Это можно значительно упростить, используя concat(). Хорошо. Можно немного упростить. :) - person Tomalak; 16.10.2013
comment
Мой XSLT-джитсу заржавел =) - person Rubens Farias; 16.10.2013

Самый простой/быстрый способ сделать это (если у вас есть XPath 2):

 string-join(//text / concat("T", position(), "=", .), "&")

Или лучше, если вам действительно нужен кодированный URL-адрес, и поместите его дословно в XSLT:

 string-join(//text / concat("T", position(), "=", encode-for-uri(.)), "&amp;")
person BeniBela    schedule 17.10.2013

Это можно сделать в XPath 2.0 (и, следовательно, XSLT 2.0) следующим образом:

string-join(
  for $i in 1 to count(//text) 
    return concat('T', $i, '=', (//text)[$i]), 
  '&')
person Michael Kay    schedule 16.10.2013