我需要一个XSL样式表,它允许我在前一个兄弟的最后一个元素之前移动一个XML元素进行打印

时间:2011-03-14 19:46:01

标签: xslt xslt-1.0

拜托,我需要你的帮助!!

我需要一个XSL样式表,它允许我在前一个兄弟的最后一个元素(< tools>或者它可能是< parts>)之前移动一个XML元素进行打印。我的if语句是:

IF(< tools>或< parts>)和< planning>然后存在于XML中 MOVE< planning>打印BEFORE(< tools>或< parts>) 否则只需< apply-templates />。

我尝试过几件事情,但在< tools>之前我无法打印它。或者在某些文件中,它是< parts>。

XML如下:

<work>
    <prelim>
        <code>ABC</code>
        <source>DEF</source>
        <tools>Includes codes for a table</tools>
    </prelim>
    <main>
        <planning>Text for Planning</planning>
        <p>blah blah blah</p>
    </main>
</work>

如果上述条件存在,我希望输出为:

<work>
    <prelim>
        <code>ABC</code>
        <source>DEF</source>
        <planning>Text for Planning</planning>
        <tools>Includes codes for a table</tools>
    </prelim>
    <main>
        <p>blah blah blah</p>
    </main>
</work>

任何人都可以帮我解决这个问题吗?

提前致谢!!

琳达

2 个答案:

答案 0 :(得分:1)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="tools[not(preceding-sibling::parts)]|
                         parts[not(preceding-sibling::tools)]">
        <xsl:for-each select="../../main/planning">
            <xsl:call-template name="identity"/>
        </xsl:for-each>
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="planning"/>
</xsl:stylesheet>

输出:

<work>
    <prelim>
        <code>ABC</code>
        <source>DEF</source>
        <planning>Text for Planning</planning>
        <tools>Includes codes for a table</tools>
    </prelim>
    <main>
        <p>blah blah blah</p>
    </main>
</work>

模式的其他方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="tools[not(preceding-sibling::parts)]|
                         parts[not(preceding-sibling::tools)]">
        <xsl:apply-templates select="../../main/planning" mode="copy"/>
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="planning"/>
    <xsl:template match="node()|@*" mode="copy">
        <xsl:call-template name="identity"/>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

此转化:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match=
 "/*/*[1]/*[not(self::tools or self::parts)]
             [not(preceding-sibling::*[self::tools or self::parts])]
                                         [last()]">
  <xsl:call-template name="identity"/>
  <xsl:copy-of select="../following-sibling::*[1]/planning"/>
 </xsl:template>
 <xsl:template match="planning"/>
</xsl:stylesheet>

应用于提供的XML文档时:

<work>
    <prelim>
        <code>ABC</code>
        <source>DEF</source>
        <tools>Includes codes for a table</tools>
    </prelim>
    <main>
        <planning>Text for Planning</planning>
        <p>blah blah blah</p>
    </main>
</work>

产生完全正确的结果:

<work>
   <prelim>
      <code>ABC</code>
      <source>DEF</source>
      <planning>Text for Planning</planning>
      <tools>Includes codes for a table</tools>
   </prelim>
   <main>
      <p>blah blah blah</p>
   </main>
</work>

<强>解释

  1. 身份规则(模板)按“原样”复制每个节点。

  2. 两个模板覆盖了身份规则 - 一个用于阻止planning的“就地复制”,另一个用于执行实际的移动操作。

  3. 执行移动操作的覆盖模板具有以下属性:

    它匹配以下元素:1)是top元素的第一个子元素的子元素,2)不是toolparts,并且3)没有前面的兄弟元素toolparts和4)是满足1),2)和3)的任何元素的最后一个。

    操作很简单:此模板通过按名称调用标识规则来复制当前节点。然后它复制其“堂兄” - 其父元素的第一个兄弟姐妹的planning子女。