XSL模板匹配父项的属性

时间:2013-10-07 21:43:50

标签: xml xslt

我有一些看起来像这样的XML:

  <section class="DoCO:Section">
    <h1 class="DoCO:SectionTitle" id="42" page="3" column="2">EXPERIMENT</h1>
    <region class="DoCO:TextChunk" id="43" page="3" column="2">lots of body<xref ref-type="bibr" rid="R7" id="35" class="deo:Reference">7</xref> text</region>
    <region class="DoCO:FigureBox" id="F4">
      <image class="DoCO:Figure" src="2cn.page_003.image_04.png" thmb="2cn.page_003.image_04-thumb.png"/>
      <caption class="deo:Caption" id="44" page="3" column="2">Figure 4: Experimental Setup</caption>
    </region>

我一直在使用以下XSL来分别匹配外部参照元素:

                <xsl:for-each select="article/body/section">
                    <sec>
                        <xsl:for-each select="h1">
                            <title>
                                <xsl:value-of select="string(.)"/>
                            </title>
                        </xsl:for-each> 

                        <xsl:for-each select="region">
                            <p>
                                <xsl:apply-templates/>
                            </p>
                        </xsl:for-each>
</xsl:template>
<xsl:template match="xref">
    <xref/>
</xsl:template>

但是,我希望能够在给定区域内将图像和标题元素组合在一起,而无需更改当前处理区域元素的开放式方式,因此我尝试执行以下操作:

<xsl:template match="@class[.='DoCO:FigureBox']">
    <fig xmlns:xlink="http://www.w3.org/1999/xlink">
        <graphic>
            <xsl:for-each select="image">
                <xsl:attribute name="xlink:href">
                    <xsl:value-of select="@src"/>
                </xsl:attribute>
            </xsl:for-each>
        </graphic>
        <caption>
            <xsl:for-each select="caption">
                <xsl:value-of select="string(.)"/>
            </xsl:for-each>
        </caption>
    </fig>
</xsl:template>

但匹配=“@ class [。='DoCO:FigureBox']”似乎没有被解雇。是否无法匹配xsl:apply-templates的父元素的属性,就像在子元素上匹配一样?

谢谢!

1 个答案:

答案 0 :(得分:2)

以下语法没有错误:

<xsl:template match="@class[.='DoCO:FigureBox']">

你的(第一个)问题,就在这里

<xsl:apply-templates/>

这是此

的简写
<xsl:apply-templates select="node()" />

这意味着,您没有选择任何属性,因此不会调用 @class 属性的模板匹配项。

现在,您可以将其更改为此

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

但这导致了第二个问题。在匹配 @class 的模板中,您有一些 xsl:for-each 语句,图片标题。但此时,您位于 @class 属性,而不是区域元素,因此这些 xsl:for-each 语句将一无所获。

您可能应该做的是,不要在主代码中执行<xsl:for-each select="region">,而是执行<xsl:apply-templates select="region" />。然后,您可以有两个模板,如此

<xsl:template match="region">
   <p>
        <xsl:apply-templates />
   </p>
</xsl:template>

<xsl:template match="region[@class='DoCO:FigureBox']">
    <fig xmlns:xlink="http://www.w3.org/1999/xlink">
        <graphic>
            <xsl:for-each select="image">
                <xsl:attribute name="xlink:href">
                    <xsl:value-of select="@src"/>
                </xsl:attribute>
            </xsl:for-each>
        </graphic>
        <caption>
            <xsl:for-each select="caption">
                <xsl:value-of select="string(.)"/>
            </xsl:for-each>
        </caption>
    </fig>
</xsl:template>

在这种情况下,XSLT处理器应优先考虑更具体的模板,因此它将覆盖您对区域元素的默认处理。

事实上,如果您每个地区总是有一个字幕图片,您可以将模板简化为:

<xsl:template match="region[@class='DoCO:FigureBox']">
    <fig xmlns:xlink="http://www.w3.org/1999/xlink">
        <graphic xlink:href="{@src}" />
        <caption>
            <xsl:value-of select="caption" />
        </caption>
    </fig>
</xsl:template>

请注意在创建属性时使用属性值模板。花括号表示要评估的表达式,而不是按字面输出。