XSL立即检查兄弟姐妹

时间:2015-03-11 10:58:57

标签: xml xslt

过去两天我的脑屁很大。我需要检查<step1>的第一个<proc>子元素是否有<note>的前一个兄弟:

<proc>
   <note>
       <trim.para>Some sort of note</trim.para>
   </note>
   <step1>
       <para>Turn off all electrical power .</para>
   </step1>
   <step1>
       <para>A second step.</para>
   </step1>
</proc>

我正在尝试使用以下XSL将<step1>元素(和子<step2>元素)转换为<proceduralStep>元素,并且没有任何运气让<note>成为包括:

<xsl:template match="step1 | step2">
        <!-- create key/value pair to store existing ids with new value for proceduralStep element-->
        <xsl:choose>
            <xsl:when test="./@id">
                <proceduralStep id="{@id}">
                    <xsl:if test="preceding-sibling::*[1][note]">
                        <xsl:for-each select="preceding-sibling::*[1][note]">
                            <note>
                                <notePara>
                                    <xsl:value-of select="./trim.para"/>
                                </notePara>
                            </note>
                        </xsl:for-each>
                    </xsl:if>
                        <xsl:apply-templates/>
                </proceduralStep>
            </xsl:when>
            <xsl:otherwise>
                <proceduralStep>
                    <xsl:if test="preceding-sibling::*[1][note]">
                        <xsl:for-each select="preceding-sibling::*[1][note]">
                            <note>
                                <notePara>
                                    <xsl:value-of select="./trim.para"/>
                                </notePara>
                            </note>
                        </xsl:for-each>
                    </xsl:if>
                        <xsl:apply-templates/>
                </proceduralStep>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

输出:

<mainProcedure>
    <proceduralStep>
      <para>Turn off all electrical power.</para>
    </proceduralStep>
    <proceduralStep>
      <para>A second step.</para>
    </proceduralStep>
</mainProcedure>

我需要输出:

<mainProcedure>
    <proceduralStep>
        <note>
            <notePara>Some sort of note</notePara>
        </note>
       <para>Turn off all electrical power.</para>
    </proceduralStep>
    <proceduralStep>
      <para>A second step.</para>
    </proceduralStep>
</mainProcedure>

我已经有一个模板可以在<note><step1>元素(或其他任何地方)内部处理<step2>元素时处理它们。我创建了一个空模板来禁止将proc \ note放在我的输出中:

<xsl:template match="note[parent::proc]"></xsl:template>

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

<xsl:template match="note/trim.para">
    <notePara>
        <xsl:apply-templates/>
     </notePara>
</xsl:template>

我发誓我以前做过这件事,但我今天早上(或昨天上午就此事)没有回忆起来。

1 个答案:

答案 0 :(得分:1)

正如马丁在评论中所说,你需要使用self::轴来检查前面的兄弟。您还可以删除if,并通过复制现有的id属性来显着减少代码重复:

<xsl:template match="step1 | step2">
    <!-- create key/value pair to store existing ids with new value for proceduralStep
         element-->
    <proceduralStep>
        <!-- copy id attribute from step1|step2 if it exists, do nothing if not -->
        <xsl:copy-of select="@id" />
        <!-- no need for an if here - if the immediately preceding sibling is not a
             note then the select will return an empty node set, which makes the
             for-each a no-op -->
        <xsl:for-each select="preceding-sibling::*[1][self::note]">
            <note>
                <notePara>
                     <xsl:value-of select="./trim.para"/>
                </notePara>
            </note>
        </xsl:for-each>
        <xsl:apply-templates/>
    </proceduralStep>
</xsl:template>