Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old July 27th, 2005, 07:29 AM
Registered User
 
Join Date: Oct 2004
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default renumbering xml elements with XSLT

After reading around Google search results, and experimenting a bit I'm stuck with trying to renumber elements in an XML source via XSLT.

If I have something like:

<something uid="1" />
<something uid="2" />
<something uid="3" />

What would be the most straight-forward XSLT code to allow me to pass in a parameter to allow me to insert an element between uid's 1 and 2, giving it's uid attribute the value of "2" (ie: the same value as the element it is inserted before) and renumbering the subsequent elements' uid attributes accordingly to give me:

<something uid="1" />
<something uid="2" /> - this is the newly inserted element
<something uid="3" /> - this was formally UID="2"
<something uid="4" /> - this was formally UID="3"

Note that uid="1" remains constant, it is only uid="2" and uid="3" that get renumbered to allow for the newly inserted element.

Thanks

 
Old July 27th, 2005, 07:46 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Something like this perhaps:

<xsl:for-each select="something[@uid < $param]">
  <something uid="{@uid}"/>
</
<... new element here ...>
<xsl:for-each select="something[@uid >= $param]">
  <something uid="{@uid+1}"/>
</

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old July 27th, 2005, 08:01 AM
Registered User
 
Join Date: Oct 2004
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Michael!
I think I understand, but in the case that I have in mind the XSLT that I am using does not shout to me an obvious "before", "middle" and "after" section in which to port your code. If it wouldn't be too presuming, please could you give me a pointer as to how I would merge your code into the following.

This XSLT will take a new Test Case and copy it into the XML stream at the top (I then use a separate stylesheet to order it in any manner desired). However the newly inserted Test Case will have the same UID as an existing one - hence the problem described in my original post.
Many thanks

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" encoding="utf-8" indent="yes" />

<xsl:param name="uid" />
<xsl:param name="oid" />
<xsl:param name="active" />
<xsl:param name="type" />
<xsl:param name="attach" />
<xsl:param name="item" />
<xsl:param name="result" />
<xsl:param name="testcomments" />
<xsl:param name="datelastmodified" />

<xsl:template match="/testsuite">

<xsl:element name="testsuite">
    <xsl:element name="testcase">
      <xsl:attribute name="uid"><xsl:value-of select="$uid" /></xsl:attribute>
      <xsl:attribute name="oid"><xsl:value-of select="$oid" /></xsl:attribute>
      <xsl:element name="active"><xsl:value-of select="$active" /></xsl:element>
      <xsl:element name="type"><xsl:value-of select="$type"/></xsl:element>
      <xsl:element name="attach"><xsl:value-of select="$attach" /></xsl:element>
      <xsl:element name="item"><xsl:value-of select="$item" /></xsl:element>
      <xsl:element name="result"><xsl:value-of select="$result" /></xsl:element>
      <xsl:element name="testcomments"><xsl:value-of select="$testcomments" /></xsl:element>
    </xsl:element>
    <xsl:apply-templates />
</xsl:element>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
 
Old July 27th, 2005, 08:31 AM
Registered User
 
Join Date: Oct 2004
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Oh dear - I'm not doing well! I've tried the following, thinking that if I perform the test after copying from the source to the output tree, but before applying that it ought to perform the test (there's logic in there somewhere folks!), but to no avail I'm afraid :(

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:if test="testcase[@oid >= $oid]">
        <testcase oid="{@oid+1}" />
      </xsl:if>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

 
Old July 27th, 2005, 08:53 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I can't really follow the logic of your code - it seems to handle a single testsuite that contains a single testcase.

You can of course invert the code I gave you so that when processing an individual <something> you use an xsl:choose condition to decide whether it is before or after the insertion point and therefore whether to add 1 to the @uid attribute:

<xsl:template match="something">
  <something>
  <xsl:attribute name="uid">
    <xsl:choose>
       <xsl:when test="@uid >= $param">
          <xsl:value-of select="@uid"/>
       </
       <xsl:otherwise>
          <xsl:value-of select="@uid+1"/>
       </


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old July 27th, 2005, 09:17 AM
Registered User
 
Join Date: Oct 2004
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default

quote:" I can't really follow the logic of your code"

Apologies - the code works by having an XML file already containing test cases. When the parameters for a new test case are passed to the XSLT code, and that XSLT used to manipulate the XML it will add a single new Test Case to the top of the file. As described though, I need to modify the XSLT to add 1 to the uid of the existing test cases as they are written to the output by the copy in the template at the end.





Similar Threads
Thread Thread Starter Forum Replies Last Post
Finding nested elements XSLT 1? Budbertzerofluff XSLT 2 November 15th, 2008 02:45 PM
XSLT: ONE template to transform all the elements Behl_Neha XSLT 8 December 15th, 2007 07:31 PM
XSLT - Grouping by Attribute but same elements vinaura XSLT 2 July 18th, 2007 10:34 PM
adding elements in XSLT 1.0 spencer.clark XSLT 3 July 25th, 2005 09:41 AM
Grouping Elements using XSLT mathuranuj XSLT 2 June 21st, 2005 02:56 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.