【问题标题】:Apply-templates with different modes应用不同模式的模板
【发布时间】:2017-02-20 13:51:14
【问题描述】:

我想使用应用模板处理节点,但使用不同的模式为序列中的所有节点匹配正确的模板规则。

XML:

<?xml version="1.0" encoding="UTF-8"?>
<story>
    <p class="h1">
        <content>heading</content>
        <br/>
    </p>
    <p>
        <content>some text</content>
        <br/>
        <content>more text...</content>
    </p>
</story>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:element name="div">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="p">
        <xsl:choose>
            <xsl:when test="@class='h1'">
                <xsl:element name="h1">
                    <!--apply-tempaltes mode:#default, for br mode:ignore-->
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="p">
                    <!--apply-tempaltes mode:#default-->
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="content" mode="#default">
        <xsl:element name="span">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="br" mode="#default">
        <xsl:element name="br"/>
    </xsl:template>

    <xsl:template match="br" mode="ignore"/>

</xsl:stylesheet>

想要的输出:

<?xml version="1.0" encoding="UTF-8"?>
<story>
    <h1 class="h1"><span>heading</span>    
    </h1>
    <p><span>some text</span> 
        <br/>
        <span>more text...</span> 
    </p>
</story>

XSLT 版本是 2.0。我知道,还有其他方法可以实现此示例所需的输出,但我想使用模式属性。

【问题讨论】:

  • 你还没有告诉我们想要的输出是什么。我们要读懂你的心吗?我不知道这是什么意思:“apply-tempaltes mode:#default, for br mode:#ignore”。您需要告诉我们您要完成的工作。
  • 我想知道,我是否可以对序列中的所有项目使用不同的模式。只要我使用模式ignore#default 将不起作用。我可以使用mode="#all" 作为模板match="content"。我敢肯定,有更好的解决方案。
  • 仍然不清楚,请告诉我们目标,而不是询问模式。如果br 元素在p[@class = 'h1'] 元素内,您是否要忽略(即:不复制到结果文档)?
  • 好吧,也许我选择了一个不好的例子。目标是根据名称以不同的模式处理&lt;xsl:apply-templates/&gt; 的项目。是的,我想忽略 brelements 但不在匹配模式中使用谓词。
  • 你可以写两个xsl:apply-templates,例如&lt;xsl:apply-templates select="node() except br"/&gt;&lt;xsl:apply-templates select="br" mode="mode-name"/&gt;,只是当你想忽略你根本不需要第二个 apply-templates 的元素时,只适用于 node() except br 就足够了。

标签: xml xslt xslt-2.0 mode


【解决方案1】:

AFAICT,你想做的事:

XSLT 2.0

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

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

<xsl:template match="p[@class='h1']">
    <h1 class="h1">
        <xsl:apply-templates mode="h1"/>
    </h1>
</xsl:template>

<xsl:template match="content" mode="#all">
    <span>
        <xsl:apply-templates mode="#current"/>
    </span>
</xsl:template>

<xsl:template match="br" mode="h1"/>

</xsl:stylesheet>

【讨论】:

  • mode="#all" 在这种情况下可以解决问题,谢谢。我认为,没有办法根据名称处理具有不同模式的序列项目?
  • 我不确定你的意思。通常,模板通过名称匹配节点,因此mode 不需要做同样的事情。当您有两个具有相同(或重叠)匹配模式的模板时,您可以使用mode。请注意,以上内容可以在不使用mode 的情况下实现,只需&lt;xsl:template match="br[ancestor::p[@class='h1']]" /&gt;
  • 我不确定这对问题中的任务是否重要,但带有模式的 XSLT 2.0 身份转换需要&lt;xsl:apply-templates select="@*|node()" mode="#current"/&gt; 而不是&lt;xsl:apply-templates select="@*|node()"/&gt;,才能使用任何模式。
  • 我的意思是:我想将apply-templates 序列的一些项目与模板模式=“#default”(在本例中为content)和一些(在本例中为br ) 使用模板模式="忽略"。我也不想在&lt;xsl:template match="br"&gt; 中使用谓词
  • @Ferestes 您必须发出两条xsl:apply-templates 指令,具有不同的模式和不同的选择表达式。我认为您不会轻易找到这将是一个好的解决方案的示例(如果只是因为它改变了处理节点的顺序)。
猜你喜欢
  • 1970-01-01
  • 2021-01-12
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多