0

我有一些看起来像这样的 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>

但是 match="@class[.='DoCO:FigureBox']" 似乎没有被触发。是否不可能像匹配子元素一样匹配 xsl:apply-templates 的父级属性?

谢谢!

4

1 回答 1

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语句,用于imagecaption。但是此时,您定位于@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>

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

于 2013-10-07T22:04:47.937 回答