Home > front end >  XSLT - Key function to get single value
XSLT - Key function to get single value

Time:11-22

I have the following xml

<Results>
    <form-type>orderform-B</form-type>
    <data>
      <form-data>
        <field>
           <name>productid-1</name>
           <value>Yes</value>
        </field>
        <field>
           <name>productid-1-qty</name>
           <value>2</value>
         </field>
         <field>
            <name>productid-3</name>
            <value>Yes</value>
         </field>
         <field>
            <name>productid-4</name>
            <value>Yes</value>
         </field>
         <field>
            <name>productid-4-qty</name>
            <value>2</value>
         </field>
         <field>
            <name>someother-field</name>
            <value>xyz</value>
         </field>
      </form-data>
    </data>
  </Results>

And the following XSLT to calculate order total:

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

<xsl:variable name="pricelist">
    <item id="productid-1">5</item> 
    <item id="productid-2">5</item> 
    <item id="productid-3">5</item> 
    <item id="productid-4">5</item> 
</xsl:variable>

<xsl:key name="price" match="item" use="@id" />
<xsl:key name="qty" match="field[ends-with(name, '-qty')]" use="name" />

<xsl:template match="/">
    <total>
        <xsl:variable name="charges">
           <xsl:apply-templates select="//data/form-data/field"/>
        </xsl:variable>
        <xsl:value-of select="sum($charges/charge)" />
    </total>    
</xsl:template>
   
<xsl:template match="field">
  <xsl:if test="key('price', name, $pricelist)">
      <xsl:variable name="price" select="key('price', name, $pricelist)" />
      <xsl:variable name="qty" select="key('qty', name)" />
      <charge>
        <xsl:value-of select="$price * $qty"/>
      </charge>
   </xsl:if>    
 </xsl:template>

</xsl:stylesheet>

I want to get the value of qty using a key but what I have above returns both the qty fieldname and the qty value where as I only want to return the value so that I can do the calculation?

  • How do I get just the qty value of the fields which have name ending with '-qty'?
  • I have some products e.g. productid-3 on the order form where there is no quantity value field defined i.e. only the product ordered is listed in which case the quantity of the ordered product is assumed to be 1. How can I refactor the xslt to accommodate that as well so that the price * qty for the charge is price * 1?

CodePudding user response:

With the keys as defined, you can of course use $qty/value (instead of $qty) to select solely the value.

Or you would need to declare the key on match="field[...]/value" use="../name" to have the key function call return the value element.

CodePudding user response:

I would do:

XSLT 2.0

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

<xsl:variable name="pricelist">
    <item id="productid-1">5</item> 
    <item id="productid-2">5</item> 
    <item id="productid-3">5</item> 
    <item id="productid-4">5</item> 
</xsl:variable>

<xsl:key name="price" match="item" use="@id" />
<xsl:key name="qty" match="field" use="name" />

<xsl:template match="/Results">
    <xsl:variable name="charges">
        <xsl:apply-templates select="data/form-data/field[value='Yes']"/>
    </xsl:variable>
    <total>
        <xsl:value-of select="sum($charges/charge)" />
    </total>    
</xsl:template>

<xsl:template match="field">
    <xsl:variable name="price" select="key('price', name, $pricelist)" />
    <xsl:variable name="qty" select="key('qty', concat(name, '-qty'))" />
    <xsl:if test="$price">
        <charge>
            <xsl:value-of select="$price * (if($qty) then $qty/value else 1)"/>
        </charge>
   </xsl:if>    
</xsl:template>

</xsl:stylesheet>

P.S. Be careful with indiscriminate applying of templates; you don't want the built-in templates to kick in and litter your result with unwanted text nodes.

  • Related