XSLT: разбить строку и сделать что-то с каждым символом

Я новичок в XSLT. Я просмотрел учебные пособия и смог сделать около 80% того, что хотел, с моим XML-документом. Однако я на чем-то застрял. В моем XML-документе есть атрибуты, состоящие из таких значений, как «ERA», «EDA», «EDAR» и т. д. По сути, эти атрибуты состоят из комбинаций букв E, D, A и R. E, D, A и R соответствуют Редактировать, Удалить, Добавить и Читать.

Если бы я делал это императивно, я бы разбил строку на составляющие ее символы, а затем проверил каждый символ, чтобы увидеть, следует ли выводить Edit, Delete, Add< /em> или Читать. Как я могу сделать что-то подобное в XSLT? Я думал об использовании функций длины и подстроки и создании какого-то цикла.


person Vivin Paliath    schedule 11.04.2011    source источник


Ответы (3)


Встроенная (или внешняя) карта:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:local="http://localhost">
    <local:map letter="E" text="Edit"/>
    <local:map letter="D" text="Delete"/>
    <local:map letter="A" text="Add"/>
    <local:map letter="R" text="Read"/>
    <xsl:template match="test">
        <xsl:copy>
            <xsl:apply-templates
             select="document('')/*/local:map[
                        contains(current(),@letter)
                     ]/@text"
             mode="sequence"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="node()|@*" mode="sequence">
        <xsl:value-of select="concat(substring(' ', 1 div (position()!=1)),.)"/>
    </xsl:template>
</xsl:stylesheet>

Выход:

<test>Edit Delete Add Read</test>

Последовательность xsl:if инструкций:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="test">
        <xsl:copy>
            <xsl:if test="contains(.,'E')">Edit </xsl:if>
            <xsl:if test="contains(.,'D')">Delete </xsl:if>
            <xsl:if test="contains(.,'A')">Add </xsl:if>
            <xsl:if test="contains(.,'R')">Read </xsl:if>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Выход:

<test>Edit Delete Add Read </test>
person Community    schedule 12.04.2011

Предполагая, что атрибут содержит только EDA и R (или вас не интересуют другие возможные значения), простой набор contains(@attr,...) в <xsl:choose...> должен работать нормально:

<xsl:choose>
  <xsl:when test="contains(@attr,'A')">
    ...
  </xsl:when>
  <xsl:when test="contains(@attr,'D')">
    ...
  </xsl:when>
  etc...
</xsl:choose>
person Jim Garrison    schedule 12.04.2011
comment
Да, он будет содержать только E, D, A, R. Это кажется намного более простым методом! - person Vivin Paliath; 12.04.2011
comment
@ Алехандро, будет ли он проверять его на каждом <xsl:when>? Или он выходит из <xsl:choose>, когда одно из предложений совпадает? - person Vivin Paliath; 13.04.2011

Я смог решить эту проблему, используя рекурсивную функцию/шаблон:

<xsl:template name="translateAccessModes">

 <xsl:param name="accessModes" />

 <xsl:if test="string-length($accessModes) > 0">

  <xsl:variable name="accessMode" select="substring($accessModes, 1, 1)" />
  <xsl:choose>
   <xsl:when test="$accessMode='E'">Edit </xsl:when>
   <xsl:when test="$accessMode='D'">Delete </xsl:when>
   <xsl:when test="$accessMode='A'">Add </xsl:when>
   <xsl:when test="$accessMode='R'">Read </xsl:when>
   <xsl:otherwise>Unrecognized Access Mode: <xsl:value-of select="$accessMode" /> </xsl:otherwise>
  </xsl:choose>

  <xsl:call-template name="translateAccessModes">
   <xsl:with-param name="accessModes" select="substring($accessModes, 2, string-length($accessModes))" />
  </xsl:call-template>

 </xsl:if>

</xsl:template>

Однако не уверен, что это лучший способ сделать это.

person Vivin Paliath    schedule 11.04.2011