<?xml version="1.0"?>
<!-- Look in the source code to see the unformatted XML document -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xmlplease="http://www.xmlplease.com/xslt"
    exclude-result-prefixes="#all">
    <xsl:output indent="yes"/>
    <xsl:variable name="document-uri" select="document-uri(.)"/>

    <xsl:function name="xmlplease:line-number">
        <xsl:param name="document-uri"/>
        <!-- similar to document-uri() -->
        <xsl:param name="node-name"/>
        <!-- e.g.: 'p' -->
        <xsl:param name="node-number"/>
        <!-- e.g.: '3', that is the third p -->
        <xsl:variable name="unparsed" select="unparsed-text($document-uri)"/>
        <xsl:variable name="unparsed2">
            <xsl:analyze-string select="$unparsed"
                regex="&lt;!--.*?--&gt;|&lt;!\[CDATA\[.*?\]\]&gt;|&lt;\?.*?\?&gt;"
                flags="s">
                <xsl:matching-substring>
                    <xsl:value-of select="replace(., '&lt;', '')"/>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </xsl:variable>
        <xsl:value-of
            select="string-length(string-join(subsequence(tokenize($unparsed2, concat('&lt;', $node-name)), 1, $node-number), ' ')) - 
            string-length(replace(string-join(subsequence(tokenize($unparsed2, concat('&lt;', $node-name)), 1, $node-number), ' '), '&#xA;', '')) + 1"
        />
    </xsl:function>

    <xsl:template match="/">
        <test>
            <xsl:apply-templates select="//xhtml:p"/>
        </test>
    </xsl:template>

    <xsl:template match="xhtml:p">

        <xsl:if test="string-length(.) gt 500">
            <xsl:variable name="n">
                <xsl:number level="any"/>
            </xsl:variable>
            <warning>
                <xsl:value-of
                    select="concat('Paragraph in line ', xmlplease:line-number($document-uri, name(), $n)), 'has', string-length(), 'characters.' "
                />
            </warning>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>
