Re: [xsl] build group of elements

Subject: Re: [xsl] build group of elements
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 25 Jun 2012 10:57:59 -0300
At 2012-06-25 14:23 +0100, henry human wrote:
Ken, thanks a lot your script is running and provide the result I expected for that data.
But now I have a more complicated case. The following script bellow we
created has a mistake but can't find what is wrong!!!

You don't say what is wrong, so I don't know how any volunteer is supposed to tell you how to correct it.


And, anyway, your XSLT is structured quite unlike my suggestion to you. You seem to approach XSLT as if it were an imperative programming language, rather than taking advantage of inherent facilities in XSLT that make this task both easier and more robust.

You are binding variables unnecessarily, and making references to node lists as if they were arrays. You are duplicating code that is essentially identical, thus requiring multiple changes if you need to fix anything, rather than sharing code for each of the four entries.

At 2012-06-25 14:26 +0100, henry human wrote:
here is the xslt and the input data


------------------------Output------------------------------ <xsl:for-each select="DATA/REF">

<xsl:variable name="adrTyp" select="@ref:ADRTYP"/>
<xsl:variable name="refs" select="REF"/>
<xsl:variable name="noOfSegments" select="xs:integer(max(( '1', xs:string(ceiling(count($refs) div 5)) )))"/>


<xsl:for-each select="1 to $noOfSegments">
<xsl:variable name="hope" select="position() * 4"/>
<L5Segment>
<xsl:if test="($refs/CDE)[$hope - 4]">
<_1st_Address_type_Code>
<xsl:value-of select="$adrTyp"/>
</_1st_Address_type_Code>
<_1st_Reference_Code>
<xsl:value-of select="($refs/CDE)[$hope - 4]"/>
</_1st_Reference_Code>
<_1st_Reference>
<xsl:value-of select="($refs/VAL)[$hope - 4]"/>
</_1st_Reference>
</xsl:if>
<xsl:if test="($refs/CDE)[$hope - 3]">
<_2nd_Address_type>
<xsl:value-of select="$adrTyp"/>
</_2nd_Address_type>
<_2nd_Reference_Code>
<xsl:value-of select="($refs/CDE)[$hope - 3]"/>
</_2nd_Reference_Code>
<_2nd_Reference>
<xsl:value-of select="($refs/VAL)[$hope - 3]"/>
</_2nd_Reference>
</xsl:if>
<xsl:if test="($refs/CDE)[$hope - 2]">
<_3rd_Address_type>
<xsl:value-of select="$adrTyp"/>
</_3rd_Address_type>
<_3rd_Reference_Code>
<xsl:value-of select="($refs/CDE)[$hope - 2]"/>
</_3rd_Reference_Code>
<_3rd_Reference>
<xsl:value-of select="($refs/VAL)[$hope - 2]"/>
</_3rd_Reference>
</xsl:if>
<xsl:if test="($refs/CDE)[$hope - 1]">
<_4th_Address_type>
<xsl:value-of select="$adrTyp"/>
</_4th_Address_type>
<_4th_Reference_Code>
<xsl:value-of select="($refs/CDE)[$hope - 1]"/>
</_4th_Reference_Code>
<_4th_Reference>
<xsl:value-of select="($refs/VAL)[$hope - 1]"/>
</_4th_Reference>
</xsl:if>


               </L5Segment>
       </xsl:for-each>
</xsl:for-each>


--------------Input--------------- <?xml version="1.0" encoding="UTF-8"?> <DATA>

               <ref:REF ref:ADRTYP="FF">
                       <CDE>SRN</CDE>
                       <VAL>4405050008759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="MM">
                       <CDE>AAA</CDE>
                       <VAL>3378781118759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="NN">
                       <CDE>BBB</CDE>
                       <VAL>2209094446927</VAL>
               </ref:REF>

               <ref:REF ref:ADRTYP="BB">
                       <CDE>BBB</CDE>
                       <VAL>4405099999999</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="CC">
                       <CDE>CCC</CDE>
                       <VAL>4444444418759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="DD">
                       <CDE>DDD</CDE>
                       <VAL>0000000046927</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="EE">
                       <CDE>EEE</CDE>
                       <VAL>2020202020202</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="GG">
                       <CDE>GGG</CDE>
                       <VAL>667676767676</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="JJ">
                       <CDE>JJJ</CDE>
                       <VAL>2828282828282</VAL>
               </ref:REF>
       </DATA>

I think you'll find that if you take an XSLT approach to the problem, rather than mimicking an imperative programming language, that any issues will be easier to find. You'll see I've only used one variable, that being for the ordinal prefix for the element names.


Without you telling us what is wrong, I've guessed what it is you want and the code is below.

I hope this helps. Though it seems you've ignored what I suggested to you in previous posts. Perhaps readers of the archive will find this somewhat helpful. The use of grouping nodes as being adjacent based on their position is a very useful approach.

. . . . . . . . . . . Ken

~/t/ftemp $ cat henry3.xml
<?xml version="1.0" encoding="UTF-8"?>
       <DATA xmlns:ref="urn:X-henry">

               <ref:REF ref:ADRTYP="FF">
                       <CDE>SRN</CDE>
                       <VAL>4405050008759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="MM">
                       <CDE>AAA</CDE>
                       <VAL>3378781118759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="NN">
                       <CDE>BBB</CDE>
                       <VAL>2209094446927</VAL>
               </ref:REF>

               <ref:REF ref:ADRTYP="BB">
                       <CDE>BBB</CDE>
                       <VAL>4405099999999</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="CC">
                       <CDE>CCC</CDE>
                       <VAL>4444444418759</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="DD">
                       <CDE>DDD</CDE>
                       <VAL>0000000046927</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="EE">
                       <CDE>EEE</CDE>
                       <VAL>2020202020202</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="GG">
                       <CDE>GGG</CDE>
                       <VAL>667676767676</VAL>
               </ref:REF>
               <ref:REF ref:ADRTYP="JJ">
                       <CDE>JJJ</CDE>
                       <VAL>2828282828282</VAL>
               </ref:REF>
       </DATA>~/t/ftemp $
~/t/ftemp $ xslt2 henry3.xml henry3.xsl
<?xml version="1.0" encoding="UTF-8"?>
<L5Segment>
   <_1st_Address_type_Code>FF</_1st_Address_type_Code>
   <_1st_Reference_Code>SRN</_1st_Reference_Code>
   <_1st_Reference>4405050008759</_1st_Reference>
   <_2nd_Address_type_Code>MM</_2nd_Address_type_Code>
   <_2nd_Reference_Code>AAA</_2nd_Reference_Code>
   <_2nd_Reference>3378781118759</_2nd_Reference>
   <_3rd_Address_type_Code>NN</_3rd_Address_type_Code>
   <_3rd_Reference_Code>BBB</_3rd_Reference_Code>
   <_3rd_Reference>2209094446927</_3rd_Reference>
   <_4th_Address_type_Code>BB</_4th_Address_type_Code>
   <_4th_Reference_Code>BBB</_4th_Reference_Code>
   <_4th_Reference>4405099999999</_4th_Reference>
</L5Segment>
<L5Segment>
   <_1st_Address_type_Code>CC</_1st_Address_type_Code>
   <_1st_Reference_Code>CCC</_1st_Reference_Code>
   <_1st_Reference>4444444418759</_1st_Reference>
   <_2nd_Address_type_Code>DD</_2nd_Address_type_Code>
   <_2nd_Reference_Code>DDD</_2nd_Reference_Code>
   <_2nd_Reference>0000000046927</_2nd_Reference>
   <_3rd_Address_type_Code>EE</_3rd_Address_type_Code>
   <_3rd_Reference_Code>EEE</_3rd_Reference_Code>
   <_3rd_Reference>2020202020202</_3rd_Reference>
   <_4th_Address_type_Code>GG</_4th_Address_type_Code>
   <_4th_Reference_Code>GGG</_4th_Reference_Code>
   <_4th_Reference>667676767676</_4th_Reference>
</L5Segment>
<L5Segment>
   <_1st_Address_type_Code>JJ</_1st_Address_type_Code>
   <_1st_Reference_Code>JJJ</_1st_Reference_Code>
   <_1st_Reference>2828282828282</_1st_Reference>
</L5Segment>~/t/ftemp $
~/t/ftemp $ cat henry3.xsl
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:ref="urn:X-henry" exclude-result-prefixes="ref"
  version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="DATA">
  <xsl:for-each-group select="ref:REF"
                      group-adjacent="(position()-1) idiv 4">
    <L5Segment>
      <xsl:for-each select="current-group()">
        <xsl:variable name="ord">
          <xsl:number value="position()" ordinal="1"/>
        </xsl:variable>
        <xsl:element name="_{$ord}_Address_type_Code">
          <xsl:value-of select="@ref:ADRTYP"/>
        </xsl:element>
        <xsl:element name="_{$ord}_Reference_Code">
          <xsl:value-of select="CDE"/>
        </xsl:element>
        <xsl:element name="_{$ord}_Reference">
          <xsl:value-of select="VAL"/>
        </xsl:element>
      </xsl:for-each>
    </L5Segment>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
~/t/ftemp $


-- Public XSLT, XSL-FO, UBL and code list classes in Europe -- Oct 2012 Contact us for world-wide XML consulting and instructor-led training Free 5-hour lecture: http://www.CraneSoftwrights.com/links/udemy.htm Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Google+ profile: https://plus.google.com/116832879756988317389/about Legal business disclaimers: http://www.CraneSoftwrights.com/legal

Current Thread