Take the value next to the last in xslt

柔情痞子 提交于 2019-12-02 17:01:07

问题


<Address>
1234Road
Unit 5 Lane
Town, City
SO1D 23Z
Customer No. 12321312312
</Address>

<Address>
21321311234Road
1234Road
Unit 5 Lane
Town, City
SO1D 23Z
Customer No. 12321312312
</Address>

Can anyone help me to take always the value of the postcode which will be always before Customer No.?

<xsl:value-of select="substring-before(substring-after(substring-after(substring-after(Address,'&#10;'),'&#10;'),'&#10;'),'&#10;')"/>

I have used the above but is not going to work on the second example. Need to find a way to take next to the last.

Note: there is Line breaks (CRLF) between each line.

Any help is much appreciated


回答1:


One possible way is to create a recursive "substring-after-last" named template, and use that passing in the substring that occurs before "Customer No. "

Try this XSLT

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

    <xsl:template match="Address">
        <xsl:call-template name="substring-after-last">
            <xsl:with-param name="text" select="$exCust" />
            <xsl:with-param name="arg" select="'&#10;'" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="substring-after-last">
        <xsl:param name="text" />
        <xsl:param name="arg" />

        <xsl:variable name="after" select="substring-after($text, $arg)" />
        <xsl:choose> 
            <xsl:when test="contains($after, $arg)">
                <xsl:call-template name="substring-after-last">
                    <xsl:with-param name="text" select="$after" />
                    <xsl:with-param name="arg" select="$arg" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$after" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

If you are only dealing with UK postcodes, which vary between 6 and 8 characters in length (including a space), you could do it via a very crude method....

<xsl:variable name="exCust" select="substring-before(., '&#10;Customer No. ')" />
<xsl:value-of select="substring-after(substring($exCust, string-length($exCust) - 8, 9), '&#10;')" />

This is a bit of a hack though, and will also fail if the preceding town/city is one character in length!




回答2:


This is rather tedious in XSLT 1.0 - I suggest you try it along these lines:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">

<!-- ... -->

<xsl:template match="Address">
    <xsl:variable name="tokens">
        <xsl:call-template name="tokenize">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
    </xsl:variable>
    <postcode>
        <xsl:value-of select="exsl:node-set($tokens)/token[last() - 1]"/>
    </postcode>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:param name="delimiter" select="'&#10;'"/>
        <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
        <xsl:if test="$token">
            <token>
                <xsl:value-of select="$token"/>
            </token>
        </xsl:if>
        <xsl:if test="contains($text, $delimiter)">
            <!-- recursive call -->
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
            </xsl:call-template>
        </xsl:if>
</xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/38508030/take-the-value-next-to-the-last-in-xslt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!