开发者

I need an XSL stylesheet that lets me move an XML element to print before the preceding-sibling’s last element

Please, I need your help!!

I need an XSL stylesheet that lets me move an XML element to print before the preceding-sibling’s last element (<tools> or it could be <parts>). My if statement is:

IF (<tools> or <parts>) and <planning> exist in the XML, then MOVE <planning> to print BEFORE (<tools> or <parts>) OTHERWISE just <apply-templates />.

I've tried several things, but I just can't get it to print before <tools> or in some files, it's <parts>.

XML is as follows:

<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<开发者_Python百科;/p>
    </main>
</work>

I want my output to be if the above condition exists:

<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>

Can anyone help me on how to achieve this?

Thanks in advance!!

Linda


This stylesheet:

<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>

Output:

<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>

Other approach with modes:

<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>


This transformation:

<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>

when applied on the provided XML document:

<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>

produces exactly the wanted, correct result:

<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>

Explanation:

  1. The identity rule (template) copies every node "as-is".

  2. Two templates override the identity rule -- one to prevent the "copy inplace" of planning, the other to do the actual move operation.

  3. The overriding template that performs the move operation has the following properties:

    It matches any element that: 1) is a child of the first child of the top element, and 2) is not a tool or parts, and 3) has no preceding sibling that is a tool or a parts, and 4) is the last of any element that satisfies 1), 2), and 3).

    The action is simple: this template copies the current node by calling the identity rule by name. Then it copies its "cousin" -- the planning child` of the first following sibling of its parent element.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜