atif
atif

Reputation: 1147

xslt xsl:analyze-string and regex expression

I have an xml file in which I have to find patterns and put a " marks around the matching specific pattern.

<xml>
<foo>
    <id>1</id>
    <description>This is section 1, this is section 1 or 2, this is section 1 and 2</description>
</foo>
</xml>

Now in file I have to find a pattern "section 1" , "section 1 or 2" and "section 1 and 2" and put a " marks around the matching word.

I have written an xslt which is like this:

  <xsl:template match="text()">

<xsl:analyze-string select="." regex="section\s\d+|section\s\d+\s+or\s+\d|section\s\d+\s+and\s+\d">
  <xsl:matching-substring>
    <xsl:if test="matches(.,'section\s\d+')" >
      <xsl:text>"</xsl:text>
      <xsl:value-of select="."/>     
      <xsl:text>"</xsl:text>       
    </xsl:if>
    <xsl:if test="matches(.,'section\s\d+\s+or\s+\d')" >
      <xsl:text>"</xsl:text>
      <xsl:value-of select="."/>     
        <xsl:text>"</xsl:text>       
    </xsl:if>
    <xsl:if test="matches(.,'section\s\d+\s+and\s+\d')" >
      <xsl:text>"</xsl:text>
      <xsl:value-of select="."/>     
      <xsl:text>"</xsl:text>       
    </xsl:if>
  </xsl:matching-substring>
  <xsl:non-matching-substring>
    <xsl:value-of select="current()"/>
  </xsl:non-matching-substring>
</xsl:analyze-string>
 </xsl:template>

The problem I am facing here is that pattern "section 1" matches all the other pattern as well so I am not getting a desire result

The above transformation result is

<xml>
  <foo>
      <id>1</id>
      <description>This is "section 1", this is "section 1" or 2, this is "section 1" and 2</description>
  </foo>
</xml>

where as i want this output.

<xml>
  <foo>
    <id>1</id>
    <description>This is "section 1", this is "section 1 or 2", this is "section 1 and 2"</description>
   </foo>
</xml>

Any ideas how to implement it... and get the desire result.

Thanks.

Upvotes: 3

Views: 16141

Answers (2)

Kevan
Kevan

Reputation: 891

A quick but inelegant answer would be to make the test matches(.,'section\s\d+') and not(matches(.,'section\s\d+\s+or\s+\d')) or some such

Upvotes: -1

David Carlisle
David Carlisle

Reputation: 5652

this appears to work on your input:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="*">
  <xsl:copy>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:analyze-string select="." regex="section\s+\d+(\s+(or|and)\s+\d+)?">
   <xsl:matching-substring>
     <xsl:text>"</xsl:text>
     <xsl:value-of select="."/>     
     <xsl:text>"</xsl:text>       
   </xsl:matching-substring>
   <xsl:non-matching-substring>
    <xsl:value-of select="current()"/>
   </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:template>

</xsl:stylesheet>

Although if you are just generating a string not elements, xsl:anayze-string is more than you need and this produces the same result:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="*">
  <xsl:copy>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:value-of  select="replace(.,'section\s+\d+(\s+(or|and)\s+\d+)?','&quot;$0&quot;')"/>
 </xsl:template>

</xsl:stylesheet>

Upvotes: 5

Related Questions