Subject: RE: [xsl] Create a bit mask ? From: <Jarno.Elovirta@xxxxxxxxx> Date: Wed, 10 Nov 2004 09:07:12 +0200 |
Hi, > I need to convert a number of elements into a single > element with a bit mask as its value. Here is a some > sample source XML snippet: > > <Rule Name="Rule1"> > <Tag Name="Tag1"/> > <Tag Name="Tag2"/> > </Rule> > <Rule Name="Rule2"> > <Tag Name="Tag1"/> > <Tag Name="Tag3"/> > </Rule> > > <Tags> > <Tag Name="Tag1"> > <Id>0</Id> > </Tag> > <Tag Name="Tag2"> > <Id>1</Id> > </Tag> > <Tag Name="Tag3"> > <Id>2</Id> > </Tag> > </Tags> > > > I need to convert this into: > > <Rule Name="Rule1"> > <TagMap>-4</TagMap> > </Rule> > <Rule Name="Rule2"> > <TagMap>-6</TagMap> > </Rule> > > The value in TagMap is a 32 bit bit-mask which > contains a 0 if the Tag applies to the rule and a 1 if > it does not. The bit position for a tag is determined > by the Tag's ID value (Starting from the right most > bit) > > So the map for Rule1 is -4 which is > 11111111111111111111111111111100 in binary. The two > zeros correspond to Tag1 (Id 0) and Tag2 (Id 1). > Map value for Rule2 is -6 which is > 11111111111111111111111111111010 corresponding to Tag1 > (Id 0) and Tag3 (Id 2). > > Can anyone help with this? I feel handicapped without > a processing loop construct and being able to redefine > the value of a variable! I am limited to using XSLT > 1.0 How does 11111111111111111111111111111100 represent -4 in binary? If I reverse the ones and zeros (what ever you call that operation in English), add one, and multiply with -1 I get the results you state. Anyhow, the stylesheet below gives you what you wanted, but as I didn't really get the mask to value conversion, you may have to rewrite it. The Bin2Dec template's from Xselerator's Standard Snippet Library, don't know who wrote it. <xsl:template match="Rule"> <xsl:copy> <xsl:apply-templates select="@*"/> <TagMap> <xsl:variable name="n"> <xsl:call-template name="Bin2Dec"> <xsl:with-param name="value"> <xsl:apply-templates select="Tag[1]"/> </xsl:with-param> </xsl:call-template> </xsl:variable> <xsl:value-of select="-($n + 1)"/> </TagMap> </xsl:copy> </xsl:template> <xsl:template match="Tag"> <xsl:param name="mask" select="'00000000000000000000000000000000'"/> <xsl:variable name="id" select="32 - ../../Tags/Tag[@Name = current()/@Name]/Id"/> <xsl:choose> <xsl:when test="following-sibling::Tag"> <xsl:apply-templates select="following-sibling::Tag[1]"> <xsl:with-param name="mask" select="concat(substring($mask, 0, $id), 1, substring($mask, $id + 1, 32))"/> </xsl:apply-templates> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat(substring($mask, 0, $id), 1, substring($mask, $id + 1, 32))"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="Tags"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- ========================================================= --> <!-- Function: Bin2Dec(<value>) => Decimal value --> <!-- Parameters:- --> <!-- <value> - the binary string to be converted to decimal --> <xsl:template name="Bin2Dec"> <xsl:param name="value" select="'0'"/> <!-- the following paremeters are used only during recursion --> <xsl:param name="bin-power" select="number(1)"/> <xsl:param name="accum" select="number(0)"/> <!-- isolate last binary digit --> <xsl:variable name="bin-digit" select="substring($value,string-length($value),1)"/> <!-- check that binary digit is valid --> <xsl:choose> <xsl:when test="not(contains('01',$bin-digit))"> <!-- not a binary digit! --> <xsl:text>NaN</xsl:text> </xsl:when> <xsl:when test="string-length($bin-digit) = 0"> <!-- unexpected end of hex string --> <xsl:text>0</xsl:text> </xsl:when> <xsl:otherwise> <!-- OK so far --> <xsl:variable name="remainder" select="substring($value,1,string-length($value)-1)"/> <xsl:variable name="this-digit-value" select="number($bin-digit) * $bin-power"/> <!-- determine whether this is the end of the hex string --> <xsl:choose> <xsl:when test="string-length($remainder) = 0"> <!-- end - output final result --> <xsl:value-of select="$accum + $this-digit-value"/> </xsl:when> <xsl:otherwise> <!-- recurse to self for next digit --> <xsl:call-template name="Bin2Dec"> <xsl:with-param name="value" select="$remainder"/> <xsl:with-param name="bin-power" select="$bin-power * 2"/> <xsl:with-param name="accum" select="$accum + $this-digit-value"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> Cheers, Jarno
Current Thread |
---|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Create a bit mask ?, Saba | Thread | RE: [xsl] Create a bit mask ?, Saba |
Re: [xsl] for i = 1 to 10, or while, Mukul Gandhi | Date | RE: [xsl] for i = 1 to 10, or while, Jarno.Elovirta |
Month |