Home > Blockchain >  XSL grouping with variables
XSL grouping with variables

Time:05-26

I have the following string within a XML element:

<foodAndBeverageNutrient__>ENER-|APPROXIMATELY||120|E14  ENER-|APPROXIMATELY||501|KJO  PRO-|APPROXIMATELY||6.6|GRM  CHOAVL|APPROXIMATELY||6.9|GRM  SUGAR-|APPROXIMATELY||1.2|GRM  FAT|APPROXIMATELY||7.1|GRM  FASAT|APPROXIMATELY||1.3|GRM  FAMSCIS|APPROXIMATELY||3.8|GRM  FAPUCIS|APPROXIMATELY||2.0|GRM  FIBTG|APPROXIMATELY||1.2|GRM  SALTEQ|APPROXIMATELY||0.5|GRM</foodAndBeverageNutrient__>

Using the following xsl with tokenize I am able to split

    <xsl:template name="foodAndBeverageNutrient_detail">
    <xsl:for-each select="tokenize(., '\ \ ')">
        <xsl:variable name="foodAndBeverageNutrient" select="tokenize(., '\|')"/>
        <nutrientDetail>
            <nutrientTypeCode>
                <xsl:value-of select="$foodAndBeverageNutrient[1]"/>
            </nutrientTypeCode> 
            <xsl:if test="$foodAndBeverageNutrient[3] !=''">
                <dailyValueIntakePercent>
                    <xsl:value-of select="$foodAndBeverageNutrient[3]"/>
                </dailyValueIntakePercent>
            </xsl:if>
            <measurementPrecisionCode>
                <xsl:value-of select="$foodAndBeverageNutrient[2]"/>
            </measurementPrecisionCode>
            <quantityContained measurementUnitCode="{$foodAndBeverageNutrient[5]}">
                <xsl:value-of select="$foodAndBeverageNutrient[4]"/>
            </quantityContained>
        </nutrientDetail>
    </xsl:for-each>
</xsl:template>

giving me the following result:

                                            <foodAndBeverageNutrientInformation>
                                         <preparationState>UNPREPARED</preparationState>
                                         <foodAndBeverageNutrient>
                                            <measurementPrecision>APPROXIMATELY</measurementPrecision>
                                            <nutrientTypeCode iNFOODSCodeValue="ENER-"/>
                                            <quantityContained>
                                               <measurementValue unitOfMeasure="E14">
                                                  <value>29</value>
                                               </measurementValue>
                                            </quantityContained>
                                         </foodAndBeverageNutrient>
                                         <foodAndBeverageNutrient>
                                            <measurementPrecision>APPROXIMATELY</measurementPrecision>
                                            <nutrientTypeCode iNFOODSCodeValue="ENER-"/>
                                            <quantityContained>
                                               <measurementValue unitOfMeasure="KJO">
                                                  <value>69</value>
                                               </measurementValue>
                                            </quantityContained>
                                         </foodAndBeverageNutrient>
                                         <foodAndBeverageNutrient>
                                            <measurementPrecision>APPROXIMATELY</measurementPrecision>
                                            <nutrientTypeCode iNFOODSCodeValue="PRO-"/>
                                            <quantityContained>
                                               <measurementValue unitOfMeasure="GR">
                                                  <value>1.4</value>
                                               </measurementValue>
                                            </quantityContained>
                                         </foodAndBeverageNutrient>
                                         <foodAndBeverageNutrient>
                                            <measurementPrecision>APPROXIMATELY</measurementPrecision>
                                            <nutrientTypeCode iNFOODSCodeValue="CHOAVL"/>
                                            <quantityContained>
                                               <measurementValue unitOfMeasure="GR">
                                                  <value>3.8</value>
                                               </measurementValue>
                                            </quantityContained>
                                         </foodAndBeverageNutrient>
                                         <foodAndBeverageNutrient>
                                            <measurementPrecision>APPROXIMATELY</measurementPrecision>
                                            <nutrientTypeCode iNFOODSCodeValue="SUGAR-"/>
                                            <quantityContained>
                                               <measurementValue unitOfMeasure="GR">
                                                  <value>3.4</value>
                                               </measurementValue>
                                            </quantityContained>
                                         </foodAndBeverageNutrient>

But i have a requirement to group by nutrientType code, so the result is that the quantityContained is repeated for each nutrientType Code like this;

<foodAndBeverageNutrient>                             
     <measurementPrecision>APPROXIMATELY</measurementPrecision>
      <nutrientTypeCode iNFOODSCodeValue="ENER-"/>
      <quantityContained>
           <measurementValue unitOfMeasure="E14">
              <value>29</value>
           </measurementValue>
       </quantityContained>
       <quantityContained>
           <measurementValue unitOfMeasure="KJO">
              <value>122</value>
           </measurementValue>
       </quantityContained>
</foodAndBeverageNutrient>

I have tried with grouping <xsl:for-each-group but it looks like I am goruping on the wrong level in the xsl so I still end up with the 'old' result. IS there a way to group with the tokenized variables to repeat the quantity section?

CodePudding user response:

An XSLT 3 example grouping your data as a sequence of arrays is

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">
  
  <xsl:template match="foodAndBeverageNutrient__">
    <xsl:for-each-group select="tokenize(., '\ \ ') ! array { tokenize(., '\|') }" group-by="?1">
      <foodAndBeverageNutrient>
        <measurementPrecision>APPROXIMATELY</measurementPrecision>
        <nutrientTypeCode iNFOODSCodeValue="{current-grouping-key()}"/>
        <xsl:apply-templates select="current-group()"/>
      </foodAndBeverageNutrient>
    </xsl:for-each-group>
  </xsl:template>
  
  <xsl:template match=".[. instance of array(*)]">
    <quantityContained measurementUnitCode="{?5}">
      <value>{?4}</value>
    </quantityContained>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:output indent="yes" method="xml"/>
  
</xsl:stylesheet>

I am not quite sure I have selected the right data but you will better know at which index you have e.g. the value.

  • Related