[xsl] pathDeterminationByGlobalVariable

Subject: [xsl] pathDeterminationByGlobalVariable
From: mankar@xxxxxxxxxxxxxxx
Date: Wed, 11 Aug 2004 16:35:14 +0300
Hallo,

I am using this xslt code:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="xml" indent="yes"/>

<xsl:variable name="root" select="/" />

<xsl:template match="ROWSET">
  <set>
  <xsl:for-each select="ROW">
  <polygon>
     <xsl:variable name="rtf">
       <xsl:for-each
select="descendant::ELEM_INFO_ITEM">
         <xsl:if test="((position() mod 3) = 1) and
(position() &gt; 1)">
           <x>
             <xsl:value-of select="." />
           </x>
         </xsl:if>
       </xsl:for-each>
     </xsl:variable>

     <xsl:for-each select="$rtf/x">
       <xsl:variable name="a" select="." />
       <xsl:if test="position() &lt; last()">

         <xsl:variable name="b"
select="following-sibling::x[1]" />
           <interior>
           <xsl:copy-of
select="$root//ORDINATES_ITEM[(position() &gt; ($a -
1)) and (position() &lt; $b) ]" />
         </interior>
      </xsl:if>
      <xsl:if test="position() = last()">
         <interior>
           <xsl:copy-of
select="$root//ORDINATES_ITEM[position() &gt; ($a -
1)]" />
         </interior>
      </xsl:if>
      </xsl:for-each>
</polygon>
</xsl:for-each>
  </set>
</xsl:template>

</xsl:stylesheet>


to transform this xml source:


<?xml version="1.0" encoding="ISO-8859-7"?>
<ROWSET>
      <ROW num="1">
            <SHAPE>
                  <ELEM_INFO>
                        <ELEM_INFO_ITEM>1</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>1003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>5</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>9</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>12</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                  </ELEM_INFO>
                  <ORDINATES>
                        <ORDINATES_ITEM>52</ORDINATES_ITEM>
                        <ORDINATES_ITEM>45</ORDINATES_ITEM>
                        <ORDINATES_ITEM>54</ORDINATES_ITEM>
                        <ORDINATES_ITEM>57</ORDINATES_ITEM>
                        <ORDINATES_ITEM>76</ORDINATES_ITEM>
                        <ORDINATES_ITEM>78</ORDINATES_ITEM>
                        <ORDINATES_ITEM>56</ORDINATES_ITEM>
                        <ORDINATES_ITEM>1</ORDINATES_ITEM>
                        <ORDINATES_ITEM>2</ORDINATES_ITEM>
                        <ORDINATES_ITEM>3</ORDINATES_ITEM>
                        <ORDINATES_ITEM>4</ORDINATES_ITEM>
                        <ORDINATES_ITEM>5</ORDINATES_ITEM>
                        <ORDINATES_ITEM>6</ORDINATES_ITEM>
                  </ORDINATES>
            </SHAPE>
      </ROW>
</ROWSET>


into this output xml:


<?xml version="1.0" encoding="UTF-8"?>
<set>
   <polygon>
      <interior>
         <ORDINATES_ITEM>76</ORDINATES_ITEM>
         <ORDINATES_ITEM>78</ORDINATES_ITEM>
         <ORDINATES_ITEM>56</ORDINATES_ITEM>
         <ORDINATES_ITEM>1</ORDINATES_ITEM>
      </interior>
      <interior>
         <ORDINATES_ITEM>2</ORDINATES_ITEM>
         <ORDINATES_ITEM>3</ORDINATES_ITEM>
         <ORDINATES_ITEM>4</ORDINATES_ITEM>
      </interior>
      <interior>
         <ORDINATES_ITEM>5</ORDINATES_ITEM>
         <ORDINATES_ITEM>6</ORDINATES_ITEM>
      </interior>
   </polygon>
</set>


As you can see, the previous xslt, creates a polygon element for each row,
which contains as
many interior elements as ELEM_INFO_ITEM elements are, in each row, with
position :
((position() mod 3) = 1) and
(position() &gt; 1)

Each interior element contains ORDINATES_ITEM elements between two
threshold positions, which
are selected specifically from ELEM_INFO_ITEM elements's values with the
previously mentioned,
specific positions, using local variables.

The global variable root is used in order to determine the appropriate path
inside the inner loop
and select the relevant ORDINATE_ITEM nodes for each interior.

I now want to extend the particular xslt code, in order to obtain the same
output, by applying
it on another similar source xml with more than one rows.I think that the
only modification
needed for this to work, is the path determination to select the
appropriate ORDINATE_ITEM
elements of each row, each time. So i keep the rest of the code unchanged
and just alter the part:

from

<interior>
           <xsl:copy-of
select="$root//ORDINATES_ITEM........

to

<interior>
           <xsl:copy-of
select="$root/ROWSET/ROW/SHAPE/ORDINATES/ORDINATES_ITEM........

so that the selected threshold positions are applied to each ROW descendant
ORDINATE_ITEMS
and not to all descendant ORDINATES_ITEM beginning from the root.

I don't know why, but it keeps on doing the same thing, i mean selects the
threshold values
correctly for each ROW, but applies them to all ORDINATE_ITEMS elements of
the source doc
and not just to the descendant ORDINATE_ITEMS elements of each ROW.

For example:

having this source:

<?xml version="1.0" encoding="ISO-8859-7"?>
<ROWSET>
      <ROW num="1">
            <SHAPE>
                  <ELEM_INFO>
                        <ELEM_INFO_ITEM>1</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>1003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>5</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>9</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>12</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                  </ELEM_INFO>
                  <ORDINATES>
                        <ORDINATES_ITEM>52</ORDINATES_ITEM>
                        <ORDINATES_ITEM>45</ORDINATES_ITEM>
                        <ORDINATES_ITEM>54</ORDINATES_ITEM>
                        <ORDINATES_ITEM>57</ORDINATES_ITEM>
                        <ORDINATES_ITEM>76</ORDINATES_ITEM>
                        <ORDINATES_ITEM>78</ORDINATES_ITEM>
                        <ORDINATES_ITEM>56</ORDINATES_ITEM>
                        <ORDINATES_ITEM>1</ORDINATES_ITEM>
                        <ORDINATES_ITEM>2</ORDINATES_ITEM>
                        <ORDINATES_ITEM>3</ORDINATES_ITEM>
                        <ORDINATES_ITEM>4</ORDINATES_ITEM>
                        <ORDINATES_ITEM>5</ORDINATES_ITEM>
                        <ORDINATES_ITEM>6</ORDINATES_ITEM>
                  </ORDINATES>
            </SHAPE>
      </ROW>
      <ROW num="2">
            <SHAPE>
                  <ELEM_INFO>
                        <ELEM_INFO_ITEM>1</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>1003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>3</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>2003</ELEM_INFO_ITEM>
                        <ELEM_INFO_ITEM>50</ELEM_INFO_ITEM>
                  </ELEM_INFO>
                  <ORDINATES>
                        <ORDINATES_ITEM>17</ORDINATES_ITEM>
                        <ORDINATES_ITEM>23</ORDINATES_ITEM>
                        <ORDINATES_ITEM>39</ORDINATES_ITEM>
                        <ORDINATES_ITEM>54</ORDINATES_ITEM>
                        <ORDINATES_ITEM>74</ORDINATES_ITEM>
                        <ORDINATES_ITEM>98</ORDINATES_ITEM>
                  </ORDINATES>
            </SHAPE>
      </ROW>
</ROWSET>


and apllying the slightly modified xsl:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="xml" indent="yes"/>

<xsl:variable name="root" select="/" />

<xsl:template match="ROWSET">
  <set>
  <xsl:for-each select="ROW">
  <polygon>
     <xsl:variable name="rtf">
       <xsl:for-each
select="descendant::ELEM_INFO_ITEM">
         <xsl:if test="((position() mod 3) = 1) and
(position() &gt; 1)">
           <x>
             <xsl:value-of select="." />
           </x>
         </xsl:if>
       </xsl:for-each>
     </xsl:variable>

     <xsl:for-each select="$rtf/x">
       <xsl:variable name="a" select="." />
       <xsl:if test="position() &lt; last()">

         <xsl:variable name="b"
select="following-sibling::x[1]" />
           <interior>
           <xsl:copy-of
select="$root/ROWSET/ROW/SHAPE/ORDINATES/ORDINATES_ITEM[(position() &gt;
($a -
1)) and (position() &lt; $b) ]" />
         </interior>
      </xsl:if>
      <xsl:if test="position() = last()">
         <interior>
           <xsl:copy-of
select="$root/ROWSET/ROW/SHAPE/ORDINATES/ORDINATES_ITEM[position() &gt; ($a
-
1)]" />
         </interior>
      </xsl:if>
      </xsl:for-each>
</polygon>
</xsl:for-each>
  </set>
</xsl:template>

</xsl:stylesheet>


I am getting this result:


<?xml version="1.0" encoding="UTF-8"?>
<set>
   <polygon>
      <interior>
         <ORDINATES_ITEM>76</ORDINATES_ITEM>
         <ORDINATES_ITEM>78</ORDINATES_ITEM>
         <ORDINATES_ITEM>56</ORDINATES_ITEM>
         <ORDINATES_ITEM>1</ORDINATES_ITEM>
         <ORDINATES_ITEM>74</ORDINATES_ITEM>
         <ORDINATES_ITEM>98</ORDINATES_ITEM>
      </interior>
      <interior>
         <ORDINATES_ITEM>2</ORDINATES_ITEM>
         <ORDINATES_ITEM>3</ORDINATES_ITEM>
         <ORDINATES_ITEM>4</ORDINATES_ITEM>
      </interior>
      <interior>
         <ORDINATES_ITEM>5</ORDINATES_ITEM>
         <ORDINATES_ITEM>6</ORDINATES_ITEM>
      </interior>
   </polygon>
   <polygon>
      <interior>
         <ORDINATES_ITEM>54</ORDINATES_ITEM>
         <ORDINATES_ITEM>57</ORDINATES_ITEM>
         <ORDINATES_ITEM>76</ORDINATES_ITEM>
         <ORDINATES_ITEM>78</ORDINATES_ITEM>
         <ORDINATES_ITEM>56</ORDINATES_ITEM>
         <ORDINATES_ITEM>1</ORDINATES_ITEM>
         <ORDINATES_ITEM>2</ORDINATES_ITEM>
         <ORDINATES_ITEM>3</ORDINATES_ITEM>
         <ORDINATES_ITEM>4</ORDINATES_ITEM>
         <ORDINATES_ITEM>5</ORDINATES_ITEM>
         <ORDINATES_ITEM>6</ORDINATES_ITEM>
         <ORDINATES_ITEM>39</ORDINATES_ITEM>
         <ORDINATES_ITEM>54</ORDINATES_ITEM>
         <ORDINATES_ITEM>74</ORDINATES_ITEM>
         <ORDINATES_ITEM>98</ORDINATES_ITEM>
      </interior>
   </polygon>
</set>

The polygon elements are correctly created for each row.The number of
created interior elements
is also correct for each row.The threshold values are also correctly
selected for each row.
I mean, i am saying select all ORDINATEs_ITEM elemnts from position 5 to
position 8 as content of
the first interior element of the first row and it does this, but it also
adds ORDINATE_ITEM elements
from position 5 to position 8 that belong to the second row. The same thing
happens with the
ORDINATES_ITEM elements which are conetnt of the interior element of the
second row.It does not
just select the ORDINATES_ITEM from position 3 to the last as it should be,
but it also selects
ORDINATE_ITEM elements from the first row between the same positions
I know the problem is the use of the Global variable.I mean it keeps on
selecting from all root's descendants ORDINATES_ITEM elements.I tried
modifying the value of the global variable as well, but i can't still avoid
this from happening.Does anyone have any idea of how to fix this?

Thanks


Regards
Manousos

Current Thread