Search code examples
xmlxpathxqueryxslt-2.0

HOW TO WRAP THE 'styled-content' value in 'XREF' ELEMENT


The element ‘styled-content’ have fixed attributes @style and @style-type values and here we are try to wrap the number value in 'xref' element which are seprated with character as ',' 'and', '–'. Below is example case:

NOTE: The element 'styled-content' attributes are fixed, but can have other element like as 'italic' & 'bold' upder the 'p' element. these element also should be retained. Moreover 'styled-content' element could be different-2 parent element other than 'p'.

INPUT XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;14.19</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;15.39A</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;14A.24</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;14.11, 14.15</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;14.11, 14.15, 14.16</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;14.13&#x2013;14.18</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;8.3A&#x2013;8.3F</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;13.44, 14.2&#x2013;14.6</styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;14.31, 14.50, and 14.85</styled-content></p>
</root>

EXPECTED OUTPUT:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;<xref>14.19</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;<xref>15.39A</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;<xref>14A.24</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>14.11</xref>, <xref>14.15</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>14.11</xref>, <xref>14.15</xref>, <xref>14.16</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>14.13</xref>&#x2013;<xref>14.18</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>8.3A</xref>&#x2013;<xref>8.3F</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>13.44</xref>, <xref>14.2</xref>&#x2013;<xref>14.6</xref></styled-content></p>
<p content-type="new">A thorough review of the <bold>trust</bold> instrument (see <styled-content style="internal" style-type="Ref-internal">&#x00a7;&#x00a7;<xref>14.31</xref>, <xref>14.50</xref>, and <xref>14.85</xref></styled-content></p>
</root>

XSLT CODE:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

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

<xsl:template match="styled-content[@style='internal' and @style-type='Ref-internal' and not(ancestor::book-part[@book-part-type[.='preface']])]">
    <xsl:choose>
        <xsl:when test="not(contains(.,'chap'))">
            <styled-content style-type="{/book-part/book-meta/book-id}">
                <xsl:for-each select="tokenize(.,'&#x2013;')">
                    <xsl:if test="normalize-space(.)">
                        <xsl:choose>
                            <xsl:when test="contains(.,'&#x00a7;&#x00a7;')">
                                <xsl:text>&#x00a7;&#x00a7;</xsl:text><xref><xsl:value-of select="substring-after(.,'&#x00a7;&#x00a7;')"/></xref>
                            </xsl:when>
                            <xsl:when test="contains(.,'&#x00a7;')">
                                <xsl:text>&#x00a7;</xsl:text><xref><xsl:value-of select="substring-after(.,'&#x00a7;')"/></xref>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:if test="not(starts-with(., 'Chapter')) and not(starts-with(., 'Sections'))">
                                    <xsl:text>&#x2013;</xsl:text>
                                </xsl:if>
                                <xsl:choose>
                                    <xsl:when test="starts-with(., 'Sections')">
                                        <xsl:text>Sections </xsl:text><xref><xsl:value-of select="replace(.,'Sections ','')"/></xref>
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xref><xsl:value-of select="."/></xref>
                                    </xsl:otherwise>
                                </xsl:choose>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:if>
                </xsl:for-each>
            </styled-content>
        </xsl:when>
        <xsl:otherwise>
            <styled-content style="internal" style-type="Ref-internal">
                <xsl:apply-templates/>
            </styled-content>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Reference Link - https://xsltfiddle.liberty-development.net/6pS2B7g/1


Solution

  • This seems like a job for xsl:analyze-string:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="2.0">
        
        <xsl:param name="ref-pattern" as="xs:string">[0-9A-Z]+(\.[0-9A-Z]+)*</xsl:param>
        
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="styled-content[@style = 'internal' and @style-type = 'Ref-internal']/text()">
            <xsl:analyze-string select="." regex="{$ref-pattern}">
                <xsl:matching-substring>
                    <xref>
                        <xsl:value-of select="."/>
                    </xref>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </xsl:template>
        
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/6pS2B7g/2