【问题标题】:XSL Second-pass template failing when attribute is selected选择属性时 XSL 第二遍模板失败
【发布时间】:2014-02-14 22:32:53
【问题描述】:

我想知道是否有人可以解释为什么某个特定的 XSL 模板没有达到预期的效果。我正在使用 XSL 2.0 (Saxon HE) 生成 XSL-FO。我想反转某些字体样式(例如,斜体段落中的斜体文本变为罗马文本)。 (在我的实际 XSL 中,我将此作为双通道过程的第二部分。无论如何都会出现问题,因此为了简单起见,我的示例显示了单通道。)

示例输入:

<?xml version="1.0" encoding="utf-8"?>

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:layout-master-set>
        <fo:simple-page-master master-name="skeleton">
            <fo:region-body margin="1in"/>
        </fo:simple-page-master>
    </fo:layout-master-set>

    <fo:page-sequence master-reference="skeleton">
        <fo:flow flow-name="xsl-region-body">
            <fo:block><fo:inline font-style="italic">A Title <fo:inline color="black" font-style="italic">With Some Roman Text</fo:inline> in the Middle</fo:inline></fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

XSL 示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:fo="http://www.w3.org/1999/XSL/Format"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            version="2.0">

    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="//fo:inline[parent::*[@font-style=current()/@font-style]]/@font-style">
        <xsl:message>Found nested font-style.</xsl:message>
        <xsl:attribute name="font-style">normal</xsl:attribute>
    </xsl:template>  
</xsl:stylesheet>

我想要的结果是:

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:layout-master-set>
        <fo:simple-page-master master-name="skeleton">
            <fo:region-body margin="1in" />
        </fo:simple-page-master>
    </fo:layout-master-set>
    <fo:page-sequence master-reference="skeleton">
        <fo:flow flow-name="xsl-region-body">
            <fo:block>
                <fo:inline font-style="italic">
                    A Title
                    <fo:inline color="black" font-style="normal">
                        With Some Roman Text
                    </fo:inline>
                    in the Middle
                </fo:inline>
            </fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

这是我使用这个在线测试仪得到的结果:http://chris.photobooks.com/xml/default.htm

当我使用 Saxon 运行此转换时,内部 fo:inline 仍然是斜体,并且我的调试消息永远不会出现。

我找到了一种使用 for-each 的解决方法(如果我不尝试选择属性,而是选择匹配的 fo:inline,则会触发模板)。但我很想知道这有什么问题,在我看来,更清洁的解决方案。

谢谢!

(只是为了添加更多信息,这是一个不太理想的模板,它确实可以让我得到我想要的结果,至少到目前为止:

<xsl:template match="//fo:inline[parent::*[@font-style=(current()/@font-style)]]">
    <xsl:message>Found nested font-style.</xsl:message>
    <xsl:copy>
    <xsl:for-each select="@*">
    <xsl:message><xsl:value-of select="local-name()"/></xsl:message>
    <xsl:choose>
        <xsl:when test="local-name()='font-style'">
        <xsl:attribute name="font-style">normal</xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
        <xsl:copy-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
    </xsl:for-each>
    <xsl:apply-templates select="node()"/>
</xsl:copy> 

【问题讨论】:

    标签: xslt xslt-2.0 xsl-fo


    【解决方案1】:

    可能和这条线有关……

    <xsl:template match="//fo:inline[parent::*[@font-style=current()/@font-style]]/@font-style">
    

    在 XSLT 1.0 中,出现错误...

    The current() function may not be used in a match pattern.
    

    我不确定在 XSLT 2.0 中是否会发生同样的情况,但请尝试将行更改为此,看看是否会有所不同

    <xsl:template match="//fo:inline[@font-style = parent::*/@font-style]/@font-style">
    

    【讨论】:

    • XSLT 2.0 允许在模式中使用 current()。它被定义为引用您正在针对该模式进行测试的节点。
    【解决方案2】:

    我设法获得了您正在寻找的结果,将 XPath 表达式更改为

    //fo:inline[parent::*[@font-style]]/@font-style
    

    之前的 XPath 表达式不匹配文档中的任何节点,因此从未调用过模板(因此也不会打印消息)。

    【讨论】:

      【解决方案3】:

      将此作为其逻辑扩展,您可能希望将具有 奇数 个祖先 fo:inline 元素且具有与此相同 font-style 的任何 fo:inline 转换为“正常” (例如,如果您在斜体中包含斜体,那么只有三个中的中间一个想要转换回正常)。

      <xsl:template match="fo:inline[
          count(ancestor::fo:inline[@font-style = current()/@font-style]) mod 2 = 1]">
      

      这是可行的,因为 XSLT 2.0 defines current() 在一个模式中作为测试该模式的节点(在这种情况下,fo:inline 是外部谓词的主题)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-26
        • 2018-09-16
        • 2011-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-27
        • 2019-04-18
        相关资源
        最近更新 更多