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