#xml #xslt
#xml #xslt
Вопрос:
Я новичок в XSLT. Я просмотрел учебные пособия, и мне удалось выполнить около 80% того, что я хотел, с моим XML-документом. Однако я кое на чем застрял. В моем XML-документе у меня есть атрибуты, которые состоят из таких значений, как «ERA», «EDA», «EDAR» и так далее. По сути, эти атрибуты состоят из комбинаций букв E, D, A и R. E, D, A и R сопоставляются для редактирования, удаления, добавления и чтения.
Если бы я делал это в обязательном порядке, я бы разделил строку на составляющие ее символы, а затем проверил каждый символ, чтобы увидеть, следует ли мне выводить, Редактировать, удалять, добавлять или читать. Как я могу сделать что-то подобное в XSLT? Я думал об использовании функций длины и подстроки и создании какого-то цикла.
Ответ №1:
Встроенная (или внешняя) карта:
<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>
Ответ №2:
Предполагая, что атрибут содержит только E D A и 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>
Комментарии:
1. Да, он будет содержать только E, D, A, R. Это кажется намного более простым методом!
2. @Alejandro, будет ли он тестировать ее с каждым
<xsl:when>
? Или это выходит за рамки<xsl:choose>
, когда одно из предложений совпадает?
Ответ №3:
Я смог решить эту проблему, используя рекурсивную функцию / шаблон:
<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>
Однако не уверен, что это лучший способ сделать это.