选择属性时,XSL第二遍模板失败

时间:2014-02-14 22:32:54

标签: xslt xslt-2.0 xsl-fo

我想知道是否有人可以解释为什么特定的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> 

3 个答案:

答案 0 :(得分:0)

这可能与这条线有关......

<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">

答案 1 :(得分:0)

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

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

以前的XPath表达式与文档中没有节点匹配,因此从未调用过模板(因此也没有打印消息)。

答案 2 :(得分:0)

将此设置为其逻辑扩展名,您可能希望将具有奇数的祖先fo:inline元素的fo:inline转换为“正常”font-style具有相同的<xsl:template match="fo:inline[ count(ancestor::fo:inline[@font-style = current()/@font-style]) mod 2 = 1]"> 元素current() 1}}就像这个一样(例如,如果你用斜体用斜体表示斜体,那么只有三个中间的斜体想要转换回正常)。

fo:inline

这是因为模式中的XSLT 2.0 defines {{1}}作为测试模式的节点(在这种情况下是外部谓词的主语{{1}})