How to Parse Non-XML Text with xsl:analyze-string

The xsl:analyze-string instruction, introduced in XSLT 2.0, provides a native mechanism to parse, match, and structure non-XML text content using regular expressions. This article explains how xsl:analyze-string operates, its syntax and components, and how it transforms unstructured string data—such as CSV lines, log entries, and delimited text—into structured XML nodes without requiring external pre-processing tools.

The Purpose of xsl:analyze-string

Standard XSLT elements are primarily designed to navigate and transform hierarchical XML node trees. However, source documents frequently contain plain text, unstructured strings, or micro-formats within element text nodes and attributes.

The xsl:analyze-string instruction bridges this gap by evaluating an input string against a regular expression pattern. It iterates over the target text, automatically dividing it into parts that match the pattern and parts that do not, allowing you to generate XML markup or alternate text for each segment.

Syntax and Core Components

The basic structure of xsl:analyze-string relies on an input expression, a regex pattern, and two distinct handler blocks:

<xsl:analyze-string select="$inputString" regex="pattern" flags="flags">
    <xsl:matching-substring>
        <!-- Executed for portions of text matching the regex -->
    </xsl:matching-substring>
    <xsl:non-matching-substring>
        <!-- Executed for portions of text that do not match -->
    </xsl:non-matching-substring>
</xsl:analyze-string>

Key Attributes

Handling Substrings

Practical Applications

1. Converting Delimited Strings into Elements

When parsing comma-separated values (CSV) or lists where standard tokenization via tokenize() is insufficient for complex delimiters, xsl:analyze-string can identify boundaries and capture values reliably.

2. Extracting Structured Data from Plain Text

Log messages and formatted strings often contain distinct data points, such as dates, IP addresses, or error codes. By defining capture groups in the regex attribute, each component can be wrapped in a dedicated XML tag using regex-group(1), regex-group(2), and so on.

3. Hyperlinking and Text Enrichment

In mixed-content scenarios, plain text URLs or specific keywords within a paragraph can be targeted to generate HTML anchor tags (<a href="...">) while keeping the surrounding non-matching text intact.

Code Example

The following example demonstrates converting inline key-value pairs (e.g., id:101; name:Item;) into structured XML elements:

<xsl:variable name="rawText" select="'id:101; name:Widget; status:active;'"/>

<record>
    <xsl:analyze-string select="$rawText" regex="([a-zA-Z]+):([^;]+);">
        <xsl:matching-substring>
            <xsl:element name="{regex-group(1)}">
                <xsl:value-of select="normalize-space(regex-group(2))"/>
            </xsl:element>
        </xsl:matching-substring>
    </xsl:analyze-string>
</record>

Resulting Output

<record>
    <id>101</id>
    <name>Widget</name>
    <status>active</status>
</record>

Summary

The xsl:analyze-string instruction is an essential tool for modern XSLT workflows. It eliminates the need for recursive template string manipulation functions (like substring-before and substring-after), offering a declarative, regex-driven approach to convert unstructured text into fully structured XML components.