基于属性

时间:2016-12-11 19:40:36

标签: xml xslt attributes

我正在尝试修改一些将docbook文档处理成LaTeX的dblatex XSLT代码。我们已经为我们当地的需求做了很多改造,但这个让我感到难过。

“观众”属性几乎可以出现在任何docbook XML元素上。在我们的文档中,大多数元素都没有标记为此attr,但有些标记为'tech'或'nontech',例如。

<chapter audience='tech'>
  (lot of stuff)
</chapter>

我不想使用“profiling”机制,而是将LaTeX代码包装成处理具有此类属性的元素,并使用LaTeX标记,即

\technical{ \chapter (lots of stuff) }

我尝试使用xslt代码进行此包装看起来像这样:

<xsl:template match=".[@audience='tech']">
    <xsl:text>\technical{</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>}</xsl:text>
</xsl:template>

不幸的是,结果是匹配此模板的XML元素没有得到处理,只有它的女儿才会处理(正如在xslt代码上没有@select属性时所预期的那样)。所以,如果原件是

<chapter role='tech'>
   <section>blah blah</section>
</chapter>

然后LaTeX输出具有该部分的LaTeX代码,但不包含章节。

相反,如果我更改上面的xslt代码,那么它有一个明确的

<xsl:apply-templates select="."/>

然后我得到一个无限的递归。

从概念上讲,我想要做的是告诉xslt通过输出LaTeX wrapper \ technical {...}来处理具有@audience attr的XML元素,然后处理相同的元素而忽略@ audience ='科技的属性。

有办法做到这一点吗?我在其他地方使用xslt v1,虽然我想如果有必要使用xslt v2,我可以进行更改(不确定如何完成,但必须有办法...)

1 个答案:

答案 0 :(得分:0)

您可以使用自XSLT 1.0以来可用的mode属性。 模式可以区分匹配相同节点的模板,但执行不同的操作。因此,可以多次处理相同的元素。可以找到更多信息in the standard

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <xsl:apply-templates select="*" mode="firstRun"/>
    </xsl:template>

    <xsl:template match="chapter[@audience='tech']" mode="firstRun">
        <xsl:text>\technical{</xsl:text>
            <xsl:apply-templates select="." mode="secondRun"/>
        <xsl:text>}</xsl:text>
    </xsl:template>

    <xsl:template match="chapter" mode="secondRun">
        <xsl:text>\chapter{</xsl:text>
            <xsl:value-of select="."/>
        <xsl:text>}</xsl:text>
    </xsl:template>

</xsl:stylesheet>