Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

xslt - How can I strip trailing full stop (period) from text nodes

if I have a text node with a trailing full stop (or period in US english) what expression can I use to strip the full stop and leave the remainder?

e.g input

<ol>
<li>This is the first item.</li>
<li>This is the second</li>
<li>This is the 3rd. </li>
</ol> 

required output

<ol>
<li>This is the first item</li>
<li>This is the second</li>
<li>This is the 3rd</li>
</ol>  

I have this but it seems unnecessarily cumbersome

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <xsl:apply-templates select="ol"/>
    </xsl:template>
    
    <xsl:template match="ol">
        <ol>
            <xsl:apply-templates select="li"/>
        </ol>
    </xsl:template>
    
    <xsl:template match="li">
        <li><xsl:apply-templates select="text()" mode="clean-text"/></li>
    </xsl:template>
    
    <xsl:template match="text()" mode="clean-text">
        <xsl:variable name="normal-text" select="normalize-space(.)"/>
        <xsl:choose>
            <xsl:when test="substring($normal-text,string-length($normal-text),1) = '.'"><xsl:value-of select="normalize-space(substring($normal-text,1,string-length($normal-text)-1))"/></xsl:when>
            <xsl:otherwise><xsl:value-of select="$normal-text"/></xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Is there a cleverer way to achieve the same thing? BTW I am using v1.0 as this may be instantiated in a Microsoft environment. But a v2.0 solution would be of interest too

TIA

question from:https://stackoverflow.com/questions/66046708/how-can-i-strip-trailing-full-stop-period-from-text-nodes

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In XSLT 2 or 3 you have the replace function:

  <xsl:template match="ol/li[ends-with(normalize-space(.), '.')]">
      <xsl:copy>
          <xsl:value-of select="replace(., '.s*$', '')"/>
      </xsl:copy>
  </xsl:template>

In XSLT 1 enviroments you can often call into the underlying platform (e.g. Java or .NET or PHP or Python) to make use of similar string functions supporting regular expressions like .s*$ to match on the end of a string preceded by zero or more whitespace characters preceded by a single full stop character.

Or try to do it all with pure XPath 1 string functions

  <xsl:template match="ol/li[substring(normalize-space(), string-length(normalize-space())) =  '.']">
      <xsl:copy>
          <xsl:value-of select="substring(normalize-space(), 1, string-length(normalize-space()) - 1)"/>
      </xsl:copy>
  </xsl:template>

In all cases, handle copying other stuff through by the identity transformation template: https://xsltfiddle.liberty-development.net/jxNakAW


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...