应用相同类型的模板,但处理不同类型的声明

时间:2014-12-05 07:00:12

标签: xslt

我在XML之下。

 <emphasis type="italic">
                  varying from ti,e to time<star.page>58</star.page>Starch
                </emphasis>

<para indent="no">
   <star.page>18</star.page> Further to same.
</para>

这里我试图在apply-templatesstar.page,但是如果我采用<xsl:apply-templates select="./*[1][self::star.page]" mode="first"/>,那么它会在第一种情况下工作正常,但对于第二种情况,如果我使用star.page <xsl:apply-templates select="./node()[1][self::star.page]" mode="first"/> case 2,那么div将会div内的case 1之前出现的star.page <span class="font-style-italic"> varying from ti,e to time<?pb label='58'?><a name="pg_58"></a></span>2<span class="font-style-italic">Starch </span> ,值正在重复。

以下是DEmos

案例1 - enter link description here 案例2- enter link description here

预期输出如下。

案例1:

   <?pb label='18'?><a name="pg_18"></a>
   <div class="para">
       Further to same.

   </div>

案例2:

star.page

这里的条件如下。

  1. 如果para是父节点的直接子节点(虽然它是emphasispb label),则必须先创建star.page,然后再创建标记(案例2)输出)。
  2. 如果有文字,文字之间有{{1}},那么内容应该带有pb标签。(案例1输出)。
  3. 请让我知道如何解决这些问题的常见解决方案。

1 个答案:

答案 0 :(得分:1)

我不清楚你的大部分XSLT在做什么,但我会首先使用命名模板来避免重复代码。为匹配的模板提供名称也没有问题。

<xsl:template match="star.page" name="page">
    <xsl:processing-instruction name="pb">
        <xsl:text>label='</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>'</xsl:text>
        <xsl:text>?</xsl:text>
    </xsl:processing-instruction>
    <a name="{concat('pg_',.)}"/>
</xsl:template>

然后具有“first”模式的模板变为此

<xsl:template match="star.page" mode="first">
    <xsl:call-template name="page" />
</xsl:template>

你仍然可以用同样的方式调用它,或者稍微不同的条件也可以使用

<xsl:apply-templates select="star.page[not(preceding-sibling::node())]" mode="first"/>

然后,您只需要一个模板来忽略作为第一个孩子的“star.page”(因为它们已经被明确选中)

 <xsl:template match="star.page[not(preceding-sibling::node())]" />

作为简化示例,请为starers尝试此操作

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="para|emphasis">
        <xsl:apply-templates select="star.page[not(preceding-sibling::node())]" mode="first"/>

        <div>
            <xsl:choose>
                <xsl:when test="./@align">
                    <xsl:attribute name="class"><xsl:text>para align-</xsl:text><xsl:value-of select="./@align"/></xsl:attribute>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:attribute name="class"><xsl:text>para</xsl:text></xsl:attribute>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:apply-templates/>
        </div>
    </xsl:template>

    <xsl:template match="star.page[not(preceding-sibling::node())]" />

    <xsl:template match="star.page" name="page">
        <xsl:processing-instruction name="pb">
            <xsl:text>label='</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>'</xsl:text>
            <xsl:text>?</xsl:text>
        </xsl:processing-instruction>
        <a name="{concat('pg_',.)}"/>
    </xsl:template>

    <xsl:template match="star.page" mode="first">
        <xsl:call-template name="page" />
    </xsl:template>
</xsl:stylesheet>

请注意这里使用strip-space,因为严格来说,star.page不是每个示例中的第一个节点,前面有一个空白节点。

应用于此XML

<root>
    <emphasis type="italic">
      varying from ti,e to time<star.page>58</star.page>Starch
    </emphasis>
    <para indent="no">
       <star.page>18</star.page> Further to same.
    </para>
</root>

以下是输出

<div class="para">
  varying from time to time<?pb label='58'??><a name="pg_58"/>Starch
</div>

<?pb label='18'??>
<a name="pg_18"/>
    <div class="para"> Further to same.
</div>