user5000
user5000

Reputation: 39

Put a tag to a space which is between two constant words in xslt

I want to select space which is between tow specific words and put some tag there. I am using XSLT 2.0

<chapter>
  <p type="Entry"><doc refType="anchor">
    <t/>Command K (ever publish)<t/></doc><ref format="Page Number" refType="anchor" refId="sec-sec_G"/>80
  </p>
</chapter>

Expected output :

<chapter>
  <p type="Entry"><doc refType="anchor">
    <t/>Command K<t/>(ever publish)<t/></doc><ref format="Page Number" refType="anchor" refId="sec-sec_G"/>80
  </p>
</chapter>

My expected output is, putting <t/> tag between (ever publish) and Command K strings. (ever publish) and Command are constants. The character K can be changed.

tried code :

<chapter match="[starts-with('command')]//text()[ends-with('(ever publish)')]/text()">
  <t/>
</chapter>

Tried code is not working.

Upvotes: 0

Views: 73

Answers (1)

Valdi_Bo
Valdi_Bo

Reputation: 30971

Start from the identity template. Due to template prioritization details, it should be placed before the second template (see below).

Then your script should contain a template matching text() nodes, including xsl:analyze-string. The regex attribute should contain both "wanted" strings as capturing groups with a space between them.

Inside should be:

  • xsl:matching-substring printing:
    • group 1 (captured with the regex),
    • <t/> element (or whatever you want here),
    • group 2.
  • xsl:non-matching-substring, just replicating the non-matched text.

Note that the second "wanted" string contains parentheses, which are special regex chars, so to treat them literally, they should be escaped with a \.

So the whole script can look like below:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="text()">
    <xsl:analyze-string select="." regex="(Command K) (\(ever publish\))">
      <xsl:matching-substring>
        <xsl:value-of select="regex-group(1)"/>
        <t/>
        <xsl:value-of select="regex-group(2)"/>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <xsl:value-of select="."/>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:template>
</xsl:stylesheet>

Note that I added <xsl:strip-space elements="*"/> to filter out unnecessary spaces.

Upvotes: 1

Related Questions