Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

xsl:apply-templates dynamic filter

Posted on 2002-05-07
10
Medium Priority
?
863 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
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 800 total points
ID: 7067445
<recommendation>
points to b1xml2
</recommendation>
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
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…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses

730 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