sanjay
sanjay

Reputation: 1020

XSLT regex - not followed by

I need to find ',' texts which are not followed by space and and explicitly add a space value to each in XSLT.

example:

input:

<chap>
    <para>10,20,30,40,50,60,</para>
    <para>10, 20, 30, 40, 50, 60</para>
</chap>

output:

<chap>    
  <para>10,&#160;20,&#160;30,&#160;40,&#160;50,&#160;60,&#160;60,&#160;</para>
  <para>10, 20, 30, 40, 50, 60</para>
</chap>

XSLT

   <xsl:template match="text()">        
    <xsl:analyze-string select="." regex=",(?!\s)">
        <xsl:matching-substring>
            <xsl:value-of select="."/>
            <xsl:text>&#160;</xsl:text>
        </xsl:matching-substring>
    </xsl:analyze-string>     
</xsl:template>

I can use regex to do this task, but anyone can suggest me that how can I find the ',' texts witch are not followed by space character?

Upvotes: 1

Views: 477

Answers (3)

Michael Kay
Michael Kay

Reputation: 163549

I would do

string-join(tokenize($in, ',\s*'), ', ')

This assumes it would be acceptable to replace multiple spaces after the comma with a single space.

(Just noticed that @pouyan already suggested this approach in a comment).

Upvotes: 2

har07
har07

Reputation: 89315

You can use replace() function to replace comma that is followed by a non-whitespace character, say $x, with comma + &#160; + the non-whitespace char $x :

<xsl:template match="para">
    <xsl:copy>
        <xsl:value-of select="replace(.,',(\S)',',&#160;$1')"/>
    </xsl:copy>
</xsl:template>

xsltransform demo

Upvotes: 3

pouyan
pouyan

Reputation: 317

Here is an exslt-enabled xslt-1.0 solution:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:str="http://exslt.org/strings"
                extension-element-prefixes="fn str">

    <xsl:output method="xml" version="1.0" indent="yes"/>

    <xsl:template match="/">
        <xsl:apply-templates select="/node()"/>
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{name(.)}">
            <xsl:copy-of select="./@*"/>
            <xsl:apply-templates select="./node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="text()">
        <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="text()[contains(., ',')][count(str:split(., ',')) &gt; count(str:split(., ', '))]">
        <xsl:choose>
            <xsl:when test="contains(., ',')">
                <xsl:for-each select="str:tokenize(., ', ')">
                    <xsl:value-of select="."/>

                    <xsl:if test="position() != last()">
                        <xsl:text>, </xsl:text>
                    </xsl:if>
                </xsl:for-each>
            </xsl:when>

            <xsl:otherwise>
                <xsl:value-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Last text template only matches texts which contains "," not followed by space

Upvotes: 0

Related Questions