RE: [xsl] key(), generate-id question

Subject: RE: [xsl] key(), generate-id question
From: "Américo Albuquerque" <aalbuquerque@xxxxxxxxxxxxxxxx>
Date: Tue, 12 Nov 2002 12:30:55 -0000
Hi Endre.
With this case we have to change a little the templates.
First, the variable lastid have to be global, so we put it as child of
xsl:stylesheet
Then, we'll have to change the two following templates:

 <xsl:template name="generate-id">
  <xsl:variable name="last"
select="number(substring-after($lastid,'id'))"/>
  <xsl:variable name="this" select="count(preceding::*[not(@_id)])+1"/>
<!-- instead of proceding-sibling axis will use the proceding one. This
axis gets all preceding nodes no matter the level they are -->
  <xsl:variable name="temp" select="concat('00000',$last+$this)"/>
  <xsl:value-of
select="concat('id',substring($temp,string-length($temp)-5))"/>
 </xsl:template>

 <xsl:template name="biggest">
  <xsl:for-each select="//*[@_id]"> <!-- now will have to look in all
elements not just the ones at the same level -->
   <xsl:sort select="number(substring-after(@_id,'id'))"
data-type="number"/>
   <xsl:if test="position()=last()">
   <xsl:value-of select="@_id"/>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>

To wrap it up, here the complete stylesheet:
<?xml version="1.0"?>

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

 <xsl:variable name="lastid">
 <xsl:call-template name="biggest"/>
 </xsl:variable>

 <xsl:template match="*">
  <xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:attribute name="xmi.id">
  <xsl:choose>
   <xsl:when test="@_id">
   <xsl:value-of select="@_id"/>
   </xsl:when>
   <xsl:otherwise>
   <xsl:call-template name="generate-id"/>
   </xsl:otherwise>
  </xsl:choose>
  </xsl:attribute>
  <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template name="generate-id">
  <xsl:variable name="last"
select="number(substring-after($lastid,'id'))"/>
  <xsl:variable name="this" select="count(preceding::*[not(@_id)])+1"/>
  <xsl:variable name="temp" select="concat('00000',$last+$this)"/>
  <xsl:value-of
select="concat('id',substring($temp,string-length($temp)-5))"/>
 </xsl:template>

 <xsl:template name="biggest">
  <xsl:for-each select="//*[@_id]">
   <xsl:sort select="number(substring-after(@_id,'id'))"
data-type="number"/>
   <xsl:if test="position()=last()">
   <xsl:value-of select="@_id"/>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of Endre,
MAGYARI
Sent: Monday, November 11, 2002 7:57 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] key(), generate-id question



Hi,

> If the structure of your xml is diferent (probably is) then you can
> change the 'element' in the templates by 'node()'

The structure of my XML is stg like that:
<Diagram>				<-- only one or zero -->
	<Composition>			<-- 0..* -->
		<CompositionChildRole>	<-- 1-->
		<CompositionParentRole>	<-- 1-->
	</Composition>
	<Association>			<-- 0..* -->
		<AssociationRole>	<-- 2 -->
	</Association>

	<Class>				<-- 0..* -->
		<Attribute>		<-- 0..* -->

	</Class>
<Diagram>


All of these elements may have _id attribute.

My input XML, for example has no _id attribute for the root element
<Diagram> and for this reason the XSLT code you provided fails at when
tries to evaluate the previous sibling node. There is no such thing.

Because you can not assume any order regarding the input XML, I thought
somehow I need to process first all the nodes in order to obtain the
maximum ID currently present in the Document.

Does this seem reasonable?
Thank you,
Endre

> Hope that this helps you.
>
>
> -----Original Message-----
> From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> [mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx] On Behalf Of Endre
> Magyari
> Sent: Monday, November 11, 2002 7:30 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] key(), generate-id question
>
>
> > You can't control how generate-id() works, but you could do
> > something like write a named template that will generate the ID. For

> > example, you could count the number of preceding elements that don't

> > have an _ID attribute and then add that value to the numeric part of

> > the nearest preceding element that *does* have an _ID attribute. All

> > doable with normal XSLT functions.
>
>
> Based on this, as far as now I could do an enumeration of all the _id
> values (as numbers) from the document, but I have no idea how to
> select the one with the maximal value out of them. And Also, I have no

> idea how/where to store the new id values being assigned. The problem
> is that I've no experience with declarative languages. I can not get
> used to the idea that a variable can not vary. What I would do is that

> (if curr_value > max) max = curr_value. But how to do this here? Any
> help is greatly appreciated.
>
> <!-- ID Generator-->
> <xsl:template name="idgen">
>     <xsl:for-each select="node()">
>         <xsl:for-each select="@_id">
>             <xsl:number value="substring-after(current(),'id')"/>;
>         </xsl:for-each>
>     </xsl:for-each>
> </xsl:template>
>
> Thank you,
> Endre
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>
>
>
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
>

--

ing. dipl. ENDRE Magyari                                endre@xxxxxxxxx
software engineer
office:+40-66-171200
system administrator
mobile:+40-94-794735
Nextra Ltd. 		   Florilor no 28/1. RO-4100 Miercurea Ciuc.
ROMANIA


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread