XSLT 1.0 заменяет символ табуляции на HTML-элемент, содержащий вкладку - PullRequest
0 голосов
/ 28 мая 2019

Я ломал голову над заменой символов XSLT элементами HTML безрезультатно и не могу понять, как заставить XSLT заменить вкладку элементом span, содержащим вкладку.

В документе XHTML есть предварительный элемент, содержащий символы табуляции, и я обнаружил функцию шаблона замены строки XSLT, которую я использую, чтобы попытаться заменить вкладки на вкладки, окруженные интервалами:

    <xsl:template match="xhtml:pre">
        <xsl:element name="{local-name()}">

            <xsl:variable name="BodyText"><span class="tabspan">&#x9;</span></xsl:variable>

            <xsl:call-template name="replace">
                <xsl:with-param name="text" select="@*|node()"/>
                <xsl:with-param name="search" select="'&#x9;'"/>
                <xsl:with-param name="replace" select="$BodyText"/>
            </xsl:call-template>

        </xsl:element>
    </xsl:template>

    <!-- Replacement template function for XSLT 1.0 -->
    <xsl:template name="replace">
        <xsl:param name="text"/>
        <xsl:param name="search"/>
        <xsl:param name="replace"/>
        <xsl:choose>
            <xsl:when test="contains($text, $search)">
                <xsl:variable name="replace-next">
                    <xsl:call-template name="replace">
                        <xsl:with-param name="text" select="substring-after($text, $search)"/>
                        <xsl:with-param name="search" select="$search"/>
                        <xsl:with-param name="replace" select="$replace"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:value-of select="concat(substring-before($text, $search),$replace, $replace-next)"/>
            </xsl:when>
            <xsl:otherwise>
                <span class="tabspan">
                    <xsl:value-of select="$text"/>
                </span>
            </xsl:otherwise>
        </xsl:choose>

Однако, независимо от того, как я изменяю код, элементы span либо отсутствуют в выводе (если я пытаюсь назначить его с помощью переменной xsl: как указано выше), либо неправильно конвертируют экранированные символы XML, представляющие угловые скобки

&gt;
&lt;

Несмотря на странное преобразование

&quot;

До кавычки. Я, по общему признанию, смущен и не знаю достаточно о XSLT 1.0. XSLT 2.0, 3.0 и EXSLT не являются опцией из-за ограничений конвертирующей системы.

1 Ответ

0 голосов
/ 29 мая 2019

Рассмотрим следующий минимальный пример:

Input

<code><html xmlns="http://www.w3.org/1999/xhtml">
    <head/>
    <body>
    <p>This is an example.</p>
    <pre>Text before    text in the middle  text after

XSLT 1.0

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

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

<xsl:template match="xhtml:pre">
    <xsl:copy>
        <xsl:call-template name="replace-tabs">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
    </xsl:copy>
</xsl:template> 

<xsl:template name="replace-tabs">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="contains($text, '&#9;')">
            <xsl:value-of select="substring-before($text, '&#9;')"/>
            <span class="tabspan">
                <xsl:text>&#9;</xsl:text>
            </span>
            <xsl:call-template name="replace-tabs">
                <xsl:with-param name="text" select="substring-after($text, '&#9;')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Результат

<code><?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head/>
  <body>
    <p>This is an example.</p>
    <pre>Text before<span class="tabspan">  </span>text in the middle<span class="tabspan"> </span>text after

Чтобы приблизить это к вашей попытке:

<xsl:variable name="BodyText">
    <span class="tabspan">
        <xsl:text>&#9;</xsl:text>
    </span>
</xsl:variable>

<xsl:template match="xhtml:pre">
    <xsl:copy>
        <xsl:call-template name="replace">
            <xsl:with-param name="text" select="."/>
            <xsl:with-param name="searchString" select="'&#9;'"/>
            <xsl:with-param name="replacement" select="$BodyText"/>
        </xsl:call-template>
    </xsl:copy>
</xsl:template> 

<xsl:template name="replace">
    <xsl:param name="text"/>
    <xsl:param name="searchString"/>
    <xsl:param name="replacement"/>
    <xsl:choose>
        <xsl:when test="contains($text, $searchString)">
            <xsl:value-of select="substring-before($text, $searchString)"/>
            <xsl:copy-of select="$replacement"/>
            <xsl:call-template name="replace">
                <xsl:with-param name="text" select="substring-after($text, $searchString)"/>
                <xsl:with-param name="searchString" select="$searchString"/>
                <xsl:with-param name="replacement" select="$replacement"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
...