Solved

xsl:apply-templates dynamic filter

Posted on 2002-05-07
10
850 Views
Last Modified: 2010-05-18
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!!

0
Comment
Question by:PedroG
  • 7
  • 3
10 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 6995561
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
 
LVL 23

Expert Comment

by:b1xml2
ID: 6998861
PedroG, feedback pls...
0
 
LVL 2

Author Comment

by:PedroG
ID: 6998958
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
Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

 
LVL 23

Expert Comment

by:b1xml2
ID: 6999006
>>
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
 
LVL 2

Author Comment

by:PedroG
ID: 7001578
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
 
LVL 23

Expert Comment

by:b1xml2
ID: 7001618
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
 
LVL 2

Author Comment

by:PedroG
ID: 7001640
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
 
LVL 23

Expert Comment

by:b1xml2
ID: 7001743
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
 
LVL 23

Expert Comment

by:b1xml2
ID: 7001748
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
 
LVL 23

Accepted Solution

by:
b1xml2 earned 200 total points
ID: 7067445
<recommendation>
points to b1xml2
</recommendation>
0

Featured Post

How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

The Problem How to write an Xquery that works like a SQL outer join, providing placeholders for absent data on the outer side?  I give a bit more background at the end. The situation expressed as relational data Let’s work through this.  I’ve …
Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question