Xml XSLT模板不适用于新创建的元素

Xml XSLT模板不适用于新创建的元素,xml,xslt,xslt-2.0,saxon,Xml,Xslt,Xslt 2.0,Saxon,我正在使用XSLT2.0。在xsl:template(template-1)中,我使用xsl:analyze string创建具有xml:lang属性的新span元素。我有第二个模板(template-2),它向包含xml:lang属性的元素添加class属性。在我的样式表中,由第一个模板创建的新创建的span元素没有被第二个模板处理。如何修复此问题,并让第二个模板对第一个模板的结果进行操作 例如: 输入:名词的基本形式在技术上称为prātipadika(प्रातिपदिक). 期望输出:名

我正在使用XSLT2.0。在
xsl:template
(template-1)中,我使用
xsl:analyze string
创建具有
xml:lang
属性的新
span
元素。我有第二个模板(template-2),它向包含
xml:lang
属性的元素添加
class
属性。在我的样式表中,由第一个模板创建的新创建的span元素没有被第二个模板处理。如何修复此问题,并让第二个模板对第一个模板的结果进行操作

例如:

输入:
名词的基本形式在技术上称为prātipadika(प्रातिपदिक).

期望输出:
名词的基本形式在技术上称为prātipadika(प्रातिपदिक).

这个正确的输出有一个带有
xml:lang
class
属性的最终
span

样式表输出:
名词的基本形式在技术上称为prātipadika(प्रातिपदिक).

最终
span
上缺少此不正确的输出
class=“sa lang deva”

(样式表生成的附加类有助于解决某些电子书阅读器CSS支持不足的问题。)


这是我的样式表:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml"
                xpath-default-namespace="http://www.w3.org/1999/xhtml"
                xmlns:xml="http://www.w3.org/XML/1998/namespace"
                xmlns:epub="http://www.idpf.org/2007/ops">

    <xsl:output method="xhtml" encoding="utf-8" indent="no"/>

    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
            <xsl:apply-templates/>
        </html>
    </xsl:template>

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

    <!-- Template-1: Add xml:lang attribute to Devanagari text. -->
    <xsl:template match="element()/text()">
        <xsl:variable name="textValue" select="."/>
        <xsl:analyze-string select="$textValue" regex="([&#x0900;-&#x097f;]+)((\s+[&#x0900;-&#x097f;]+)*)">
            <xsl:matching-substring>
                <span xml:lang="sa-Deva"><xsl:value-of select="."/></span>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:value-of select="."/>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>

    <!-- Template-2: Add lang-* class attribute when xml:lang attribute present. -->
    <xsl:template match="*[@xml:lang]">
        <xsl:call-template name="addClass">
            <xsl:with-param name="newClass">lang-<xsl:value-of select="@xml:lang"/></xsl:with-param>
        </xsl:call-template>
    </xsl:template>

    <!-- Add a class attribute to an element. -->
    <xsl:template name="addClass">
        <xsl:param name="newClass"/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="class"><xsl:value-of select="normalize-space(concat(@class, ' ', lower-case($newClass)))"/></xsl:attribute>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

朗-

您需要将
分析字符串创建的节点捕获到一个变量中,然后对其应用模板。您可以使用模板模式来避免无限递归

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml"
                xpath-default-namespace="http://www.w3.org/1999/xhtml"
                xmlns:xml="http://www.w3.org/XML/1998/namespace"
                xmlns:epub="http://www.idpf.org/2007/ops">

    <xsl:output method="xhtml" encoding="utf-8" indent="no"/>

    <xsl:template match="/">
        <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
            <xsl:apply-templates/>
        </html>
    </xsl:template>

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

    <!-- Template-1: Add xml:lang attribute to Devanagari text. Note no
         mode attribute, so only applies in default mode. -->
    <xsl:template match="text()">
        <xsl:variable name="textValue" select="."/>
        <xsl:variable name="nodes" as="node()*">
            <xsl:analyze-string select="$textValue" regex="([&#x0900;-&#x097f;]+)((\s+[&#x0900;-&#x097f;]+)*)">
                <xsl:matching-substring>
                    <span xml:lang="sa-Deva"><xsl:value-of select="."/></span>
                </xsl:matching-substring>
                <xsl:non-matching-substring>
                    <xsl:value-of select="."/>
                </xsl:non-matching-substring>
            </xsl:analyze-string>
        </xsl:variable>
        <!-- apply templates to generated nodes, but with a mode that stops
             this template from firing again -->
        <xsl:apply-templates select="$nodes" mode="no-deva" />
    </xsl:template>

    <!-- Template-2: Add lang-* class attribute when xml:lang attribute present. -->
    <xsl:template match="*[@xml:lang]" mode="#all">
        <xsl:call-template name="addClass">
            <xsl:with-param name="newClass">lang-<xsl:value-of select="@xml:lang"/></xsl:with-param>
        </xsl:call-template>
    </xsl:template>

    <!-- Add a class attribute to an element. -->
    <xsl:template name="addClass">
        <xsl:param name="newClass"/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="class"><xsl:value-of select="normalize-space(concat(@class, ' ', lower-case($newClass)))"/></xsl:attribute>
            <xsl:apply-templates select="@*|node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

朗-

我对原始XSLT所做的更改如下:

  • 在标识模板和“模板2”中添加了
    mode=“#all”
    ,因此它们适用于所有模式,并在相关的
    apply templates
    指令中添加了
    mode=“#current”
    ,因此它们使用当前模式进行递归
  • 包围
    分析字符串
    ,以捕获它生成的节点
  • 使用不同的模式将模板应用于这些节点

由于我(故意)没有将
mode=“#all”
添加到模板1中,因此它只在初始过程中匹配,而不是在
apply templates mode=“no deva”

过程中匹配,这非常有效!谢谢。我没有想到以这种方式捕获节点。您设置模式的方式也很有指导意义。