开发者

XSLT: Splitting a string and doing something with each character

I'm an XSLT newbie. I've gone through the tutorials and I've been able to do about 80% of what I want, with my XML document. However, I am stuck on something. In my XML document, I have attributes that consist of values like "ERA", "EDA", "EDAR", and so on. Essentially these attributes consist of combinations of the letters E, D, A, and R. The E, D, A, and R map to Edit, Delete, Add, and Read.

If I was doing this imperatively, I would开发者_开发知识库 split the string into its component characters and then check each character to see if I should output Edit, Delete, Add, or Read. How can I do something similar in XSLT? I was thinking of using the length and substring functions and making a loop of some sort.


Inline (or external) map:

<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>

Output:

<test>Edit Delete Add Read</test>

Sequence of xsl:if instructions:

<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>

Output:

<test>Edit Delete Add Read </test>


Assuming that the attribute contains only E D A and R (or you don't care about other possible values), a simple set of contains(@attr,...) in an <xsl:choose...> should work fine:

<xsl:choose>
  <xsl:when test="contains(@attr,'A')">
    ...
  </xsl:when>
  <xsl:when test="contains(@attr,'D')">
    ...
  </xsl:when>
  etc...
</xsl:choose>


I was able to solve this problem by using a recursive function/template:

<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>

Not sure if this is the best way of doing it, though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜