Solved

xsl:apply-templates dynamic filter

Posted on 2002-05-07
10
853 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
Industry Leaders: 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!

 
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

Technology Partners: 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

Suggested Solutions

Title # Comments Views Activity
Image decoding from Camera 3 107
MS Access XML Export Query Setup Multiple Tag Values 15 53
PowerShell script to remove string in xml file 3 49
Append data to an XML file 3 32
The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

734 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