Sponsored

XSLT Reference

xsl:analyze-string

XSLT 2.0 element

Processes a string against a regular expression, separating matching and non-matching substrings for independent handling.

Syntax
<xsl:analyze-string select="string" regex="pattern" flags="flags">

Description

xsl:analyze-string scans a string for all occurrences of a regular expression and divides the string into alternating matching and non-matching substrings. For each portion, it invokes the appropriate child element:

  • xsl:matching-substring — processes each matched portion.
  • xsl:non-matching-substring — processes each unmatched portion between matches.

Inside xsl:matching-substring, the regex-group() function returns captured groups from the match. The instruction processes the full string from left to right, emitting output for every segment in order.

Parameters

ParameterTypeRequiredDescription
selectXPath expressionYesThe string to analyze.
regexxs:string (AVT)YesThe regular expression pattern.
flagsxs:string (AVT)NoFlag characters: i (case-insensitive), m (multiline), s (dot-all), x (extended).

Child elements (at least one is required):

ChildDescription
xsl:matching-substringTemplate for matched portions.
xsl:non-matching-substringTemplate for non-matched portions.
xsl:fallbackFallback for processors that do not support the instruction.

Return value

A sequence of nodes and/or atomic values produced by the child templates, one per substring segment.

Examples

Marking up URLs in plain text

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<comments>
  <comment>Visit https://example.com for details or http://docs.example.org/api.</comment>
</comments>

Stylesheet:

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

  <xsl:template match="/comments">
    <div>
      <xsl:apply-templates select="comment"/>
    </div>
  </xsl:template>

  <xsl:template match="comment">
    <p>
      <xsl:analyze-string select="." regex="https?://[^\s]+">
        <xsl:matching-substring>
          <a href="{.}"><xsl:value-of select="."/></a>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
          <xsl:value-of select="."/>
        </xsl:non-matching-substring>
      </xsl:analyze-string>
    </p>
  </xsl:template>
</xsl:stylesheet>

Output:

<div>
  <p>Visit <a href="https://example.com">https://example.com</a> for details or
     <a href="http://docs.example.org/api">http://docs.example.org/api</a>.</p>
</div>

Parsing dates with capture groups

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<events>
  <event>Conference on 2026-04-18 in Berlin</event>
</events>

Stylesheet:

<?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:template match="/events">
    <parsed>
      <xsl:for-each select="event">
        <xsl:analyze-string select="." regex="(\d{{4}})-(\d{{2}})-(\d{{2}})">
          <xsl:matching-substring>
            <date year="{regex-group(1)}" month="{regex-group(2)}" day="{regex-group(3)}"/>
          </xsl:matching-substring>
        </xsl:analyze-string>
      </xsl:for-each>
    </parsed>
  </xsl:template>
</xsl:stylesheet>

Output:

<parsed>
  <date year="2026" month="04" day="18"/>
</parsed>

Notes

  • Inside attribute value templates, curly braces in the regex must be doubled: \d{{4}} to match \d{4}.
  • Both xsl:matching-substring and xsl:non-matching-substring are optional. Omitting one effectively discards those segments.
  • regex-group(0) returns the entire matched string; regex-group(n) returns the nth capture group.
  • The instruction iterates all non-overlapping matches from left to right. If no match is found, the entire string is processed as a single non-matching substring.
  • XPath regex syntax is used (XML Schema flavor), which does not support lookahead or backreferences.

See also