[SOLVED] XSL filter on Multiple input

Issue

I am trying to figure out how and where does an XSL filter need to be added to filter out multiple input. Below is my XML:

<?xml version="1.0" encoding="utf-8"?>
<product_list>
  <brands>
    <brand id="A1" name="ABC">ABC Brand</brand>
    <brand id="A2" name="DEF">DEF Brand</brand>
  </brands>
  <groups>
    <group id="PN08" name="Air Pneumatic Parts"/>
    <group id="EL04" name="Lamps &amp; Electrical Parts"/>
    <group id="GE06" name="General Parts"/>
  </groups>
  <group id="PN08" name="Air Pneumatic Parts">
    <product id="PN080101">
      <name>Clutch Servo - SCANIA</name>
      <brand>ABC</brand>
    </product>
    <product id="PN080102">
      <name>Clutch Servo - VOLVO</name>
      <brand>ABC</brand>
    </product>
    <product id="PN080103">
      <name>Clutch Servo - DAF</name>
      <brand>DEF</brand>
    </product>
  </group>
  <group id="EL04" name="Lamps &amp; Electrical Parts">
    <product id="EL040101">
      <name>Headlamp - MERCEDES</name>
      <brand>ABC</brand>
    </product>
  </group>
</product_list>

and my XSL:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:param name="selected_brand" select="'all'"/>
  <xsl:param name="selected_group" select="'all'"/>
  <xsl:param name="Page" select="0" />
  <xsl:template match="/">
    <html>
    <body>
    <xsl:value-of select='$selected_brand'/> Brand, <xsl:value-of select='$selected_group'/> Group, Page: <xsl:value-of select='$Page'/><br/>
    <form method="post" action="t1.asp">
      <table>
        <tr>
          <td>
            Brand
            <select name="brand" value="{$selected_brand}" onchange="submit()">
              <option value="all">
              <xsl:if test="$selected_brand='all'">
                <xsl:attribute name="selected">Selected</xsl:attribute>
              </xsl:if>
              All</option>
              <xsl:for-each select="product_list/brands/brand">
                <option value="{@name}">
                <xsl:if test="[email protected]">
                  <xsl:attribute name="selected">Selected</xsl:attribute>
                </xsl:if>
                <xsl:value-of select="@name" /> </option>
              </xsl:for-each>
            </select>
          </td>
          <td>
            Group
            <select name="group" value="{$selected_group}" onchange="submit()">
              <option value="all">
              <xsl:if test="$selected_group='all'">
                <xsl:attribute name="selected">Selected</xsl:attribute>
              </xsl:if>
              All</option>
              <xsl:for-each select="product_list/groups/group">
                <option value="{@name}">
                <xsl:if test="[email protected]">
                  <xsl:attribute name="selected">Selected</xsl:attribute>
                </xsl:if>
                <xsl:value-of select="@name" /> </option>
              </xsl:for-each>
            </select>
          </td>
        </tr>
      </table>
    </form>
    <br/>
    <xsl:apply-templates select="product_list"/>    
    </body>
    </html>
  </xsl:template>
  
  <xsl:template match="product_list">
    <table class="catalog_table">
      <xsl:apply-templates select="group"/>
    </table>
  </xsl:template>
  
  <xsl:template match="group">
    <xsl:apply-templates select="product[($selected_brand='all') or ($selected_brand=./brand)]">
      <xsl:sort select="product[@id]"/>
    </xsl:apply-templates>
  </xsl:template>
  
  <xsl:template match="product">
    <tr>
      <td><xsl:value-of select="position()"/></td>
      <td><xsl:value-of select="name"/></td>
      <td><xsl:value-of select="brand"/></td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

I manage to get the form to work with the brand but I have no idea how to add in another group filter in such way that:

  1. When Brand = All & Group = All, display all records
  2. When Brand = ABC & Group = All, display records PN080101, PN080102 & EL040101
  3. When Brand = All & Group = PN08, display records PN080101, PN080102 & PN080103
  4. When Brand = ABC & Group = EL04, display record EL040101

Where should I put the filter? It is not sitting at the same children as the product node. How should I filter out basing on the parent node?

[($selected_group='all') or ($selected_group=./group)]

Solution

Since you are selecting groups first and then products inside the group, you could put the filtering on line 59:

      <xsl:apply-templates select="group"/>

by changing it to something like this:

      <xsl:apply-templates select="group[$selected_group='all' or $selected_group=./@id]"/>

Or, alternatively, if you want to keep all your filtering in one place you could put it on line 64:

    <xsl:apply-templates select="product[($selected_brand='all') or ($selected_brand=./brand)]">

by changing it to:

    <xsl:apply-templates select="product[($selected_brand='all' or $selected_brand=./brand) and
                                         ($selected_group='all' or $selected_group=parent::group/@id)]">

Here, the key is using the parent axis to reach out to the group element that is the parent of the product.

Answered By – Jukka Matilainen

Answer Checked By – Gilberto Lyons (BugsFixing Admin)

Leave a Reply

Your email address will not be published.