xsl:apply-templates dynamic filter

Hi,

I need to dynamicaly filter the data that would be processed by a template.

The filter query is stored in a diferent nome, and it could be something like

data/row[Produto='Produto 4'].

i have a xsl that does all the tranformation. I need to restrict it to those nodes mathing the previous query

This is the xsl i'm using
<xsl:param name="filter" select="/webGrid/currentinfo/filter"/>
<xsl:value-of select="$filter"/>
<xsl:apply-templates select="$filter">

my problem is that the last line doesn't work.

If i replace the select="$filter" by the query path it works ok. How can i do it using the value stored in a diferent node ?

help please!!

LVL 2
PedroGAsked:
Who is Participating?
 
b1xml2Connect With a Mentor Commented:
<recommendation>
points to b1xml2
</recommendation>
0
 
b1xml2Commented:
the select attribute cannot accept a variable per se but a valid XPath expression.

Post us your XML and XSLT and we will what we can do.

what you could do in your case is the following:

<xsl:apply-templates select="data/row[Produto[. = $filter]]" />

or

<xsl:apply-templates select="data/*[name() = $node and Produto[. = $filter]]" />

or

<xsl:apply-templates select="*[name() = $parent and *[name() = $child and . = $filter]]" />

that's how you can use variables in your XPath statements in that it is a matter comparison and not the actual XPath expression.

Regards,

Brandon Driesen
0
 
b1xml2Commented:
PedroG, feedback pls...
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
PedroGAuthor Commented:
xml is like this

<xmldata>
<filter>data/row[Produto='004']</filter>
<data>
<row>
<Produto>
001
</Produto>
<data>
None
</data>
</row>
</data>
</xmldata>

XSL is something like this
....
<xsl:param filter select="/xmldata/filter">
<xsl:apply-templates select="$filter">

What i want is to use the value of /xmldata/filter to select the Data/row elements

the childs of data/row are dynamic
0
 
b1xml2Commented:
>>
the select attribute cannot accept a variable per se but a valid XPath expression.
<<

I have already stated that, what you are trying to do is NOT possible. You will not succeed in a hundred years with the current implementation of the XSLT Engine in every W3C XML Parser.

the select attribute of the xsl:apply-templates MUST accept a valid XPath expression and not any string.

thus, <xsl:apply-templates select="$var" /> will ALWAYS fail.

you will have to use part DOM/part XSLT to achieve this
IF you want to retain your XML Structure
=======================================================
<xmldata>
<filter>//data/row[Produto='004']</filter>
<data>
<row>
<Produto>
001
</Produto>
<data>
None
</data>
</row>
</data>
</xmldata>

First Method
=============
e.g. in client-side, MSXML3
============================
var oXML = new ActiveXObject("Msxml2.DOMDocument");
var oFilter = new ActiveXObject("Msxml2.DOMDocument");
var oXSLT = new ActiveXObject("Msxml2.DOMDocument");
oXML.async = oFilter.async = oXSLT.async = false;
oXML.load("xml/data.xml");
oXSLT.load("xslt/data.xsl");
var oNode = oXML.selectSingleNode("//filter");
if (oNode) oFilter.appendChild(oNode.cloneNode(true));
window.onload = init;
function init() {
 document.all.data = oFilter.transformNode(oXSLT);
}

Notes
=====
1. This is using the DOM to grab nodes.

2. Here, you will have to modify your XSLT.

Second Method
==============
<xmldata>
<filter>
<target name="Produto" value="004" />
</filter>
<data>
<row>
<Produto>
001
</Produto>
<data>
None
</data>
</row>
</data>
</xmldata>

<!--this will use the default settings found in the filter-->
<xsl:call-template name="data" />

<!-- this will change the settings -->
<xsl:call-template name="data">
<xsl:with-param name="value" select="'Check'" />
</xsl:call-template>

<xsl:template name="data">
<xsl:param name="child" select="//filter/target/@name" />
<xsl:param name="value" select="//filter/target/@value" />
<xsl:apply-templates select="//data/row/*[name() = $child and . = $value]" />
</xsl:template>
0
 
PedroGAuthor Commented:
it doesn't work. this is my full xml / xsl

<webGrid>
     <config>
          <columns>
               <column Name="Produto" sortable="true" filter="true"/>
               <column Name="Activo" sortable="true" filter="true"/>
               <column Name="Teste" sortable="true" filter="false"/>
          </columns>
          <buttons>
               <button Name="Acrescentar" Action="javascript:AddRow()" ID="Button1"/>
               <button Name="Apagar" Action="javascript:AddRow()" ID="Button2"/>
          </buttons>
          <pages Current="1" Count="20" fetchpageURL="services/GetPage.asp"/>
     </config>
     <data>
          <row>
               <Produto link="admin/teste.asp">Produto 4</Produto>
               <Activo>Sim</Activo>
               <Teste>2002-05-35</Teste>
          </row>
          <row>
               <Produto link="admin/teste.asp">Produto 2</Produto>
               <Activo>Sim</Activo>
               <Teste>2002-04-15</Teste>
          </row>
          <row>
               <Produto link="admin/Teste.asp">Produto 1</Produto>
               <Activo>Sim</Activo>
               <Teste>2002-04-25</Teste>
          </row>
     </data>
     <currentinfo>
          <elementid>ms__id4</elementid>
          <sortkey>activo</sortkey>
          <filter>
               <element>Produto</element>
               <value>Produto 4</value>
          </filter>
     </currentinfo>
</webGrid>


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

     <xsl:template match="/">
          <xsl:apply-templates/>
     </xsl:template>

     <xsl:template match="/webGrid">
          <xsl:param name="sortKey">
               <xsl:value-of select="/webGrid/currentinfo/sortkey"/>
          </xsl:param>          
          <xsl:param name="filterelement" select="/webGrid/currentinfo/filter/element"/>
          <xsl:param name="filtervalue" select="/webGrid/currentinfo/filter/value"/>
          element:<xsl:value-of select="$filterelement"/><br/>
          value:<xsl:value-of select="$filtervalue"/><br/>
          <xsl:apply-templates select="config"/>
          <xsl:apply-templates select="//data/row/*[name(.) = $filterelement and . = $filtervalue]">
               <xsl:sort select="*[name(.)=$sortKey]"/>
          </xsl:apply-templates>
     </xsl:template>
     
     <xsl:template match="config">
          <table>
               <tr>
                    <xsl:apply-templates select="columns/column"/>
               </tr>
          </table>
     </xsl:template>

     <xsl:template match="column">
          <td><xsl:value-of select="@Name"/></td>
     </xsl:template>
     
     <xsl:template match="row">
          <xsl:param name="currentRow" select="(.)"/>
          <BR/>TEMPLATE ROW<BR/>
          <xsl:for-each select="/webGrid/config/columns/column">
               <xsl:variable name="currentCol" select="@Name"/>
               <xsl:value-of select="@Name"/>:<xsl:value-of select="$currentRow/*[name(.)=$currentCol]"/><BR/>
          </xsl:for-each>
     </xsl:template>
     
</xsl:stylesheet>
0
 
b1xml2Commented:
What exactly do you wish to be achieved with your XSLT? What is it that you want to do ?

The HTML Output is:-
element:Produto<br />
value:Produto 4<br />
<table>
<tr>
<td>Produto</td>
<td>Activo</td>
<td>Teste</td>
</tr>
</table>
Produto 4

and what you are using:
>>
  <xsl:apply-templates select="//data/row/*[name(.) = $filterelement and . = $filtervalue]">
<<
is what I recommended. Pls let me know what HTML output are you expecting  so that I can help you.
0
 
PedroGAuthor Commented:
this is a test html
but i was expecting something like

<table>
<tr>
<td>Produto</td>
<td>Activo</td>
<td>Teste</td>
Pruduto 4<br/>sim<br/>2002-05-35
</tr>
</table>
0
 
b1xml2Commented:
that's not valid HTML.
perhaps, you meant
HTML Output
===========
<table>
<tr>
<td>Produto</td>
<td>Activo</td>
<td>Teste</td>
</tr>
<tr>
<td>Pruduto 4</td>
<td>sim</td>
<td>2002-05-35</td>
</tr>
</table>


XSLT Document
==============
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" encoding="iso-8859-1" />
<xsl:key name="data" match="row/*" use="generate-id(..)" />
<xsl:template match="/">
  <xsl:apply-templates select="webGrid/config" />
</xsl:template>

<xsl:template match="config">
<xsl:variable name="sortKey" select="//currentinfo/sortkey"/>
<xsl:variable name="filterelement" select="//currentinfo/filter/element"/>
<xsl:variable name="filtervalue" select="//currentinfo/filter/value"/>
<table>
<tr>
  <xsl:apply-templates select="columns/column"/>
</tr>
<xsl:apply-templates select="//row[*[name() = $filterelement and . = $filtervalue]]" />
</table>
</xsl:template>

<xsl:template match="column">
<td><xsl:value-of select="@Name"/></td>
</xsl:template>
   
<xsl:template match="row">
<xsl:variable name="id" select="generate-id()" />
<tr>
  <xsl:for-each select="//columns/column/@Name">
  <xsl:apply-templates select="key('data',$id)[name(.) = current()]" />
  </xsl:for-each>
</tr>
</xsl:template>

<xsl:template match="row/*">
<td><xsl:value-of select="." /></td>
</xsl:template>
   
</xsl:stylesheet>
0
 
b1xml2Commented:
a slight amendment so that the sorting can be achieved.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" encoding="iso-8859-1" />
<xsl:key name="data" match="row/*" use="generate-id(..)" />
<xsl:template match="/">
  <xsl:apply-templates select="webGrid/config" />
</xsl:template>

<xsl:template match="config">
<xsl:variable name="sortKey" select="//currentinfo/sortkey"/>
<xsl:variable name="filterelement" select="//currentinfo/filter/element"/>
<xsl:variable name="filtervalue" select="//currentinfo/filter/value"/>
<table>
<tr>
  <xsl:apply-templates select="columns/column"/>
</tr>
<xsl:apply-templates select="//row[*[name() = $filterelement and . = $filtervalue]]">
<xsl:sort select="*[name() = $sortKey]" />
</xsl:apply-templates>
</table>
</xsl:template>

<xsl:template match="column">
<td><xsl:value-of select="@Name"/></td>
</xsl:template>
   
<xsl:template match="row">
<xsl:variable name="id" select="generate-id()" />
<tr>
  <xsl:for-each select="//columns/column/@Name">
  <xsl:apply-templates select="key('data',$id)[name(.) = current()]" />
  </xsl:for-each>
</tr>
</xsl:template>

<xsl:template match="row/*">
<td><xsl:value-of select="." /></td>
</xsl:template>
   
</xsl:stylesheet>
0
All Courses

From novice to tech pro — start learning today.