Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Filter for multiple Values

Status
Not open for further replies.

bont

Programmer
Sep 7, 2000
200
US
I have a HTML form that will pass a value via URL such as this:

FILTER=ID=01|ID=76|ID=45?....

Basically, what I would like to do is use this information in my XML doc Viewable Here

As you can see, I want to only display matches for the ID specified. The problem is that the ID number may vary in number.

How can I filter values dynamically?

 
OK, I will give a little more description. I have a statemet such as this:

I can type this:

Code:
<xsl:for-each select="PLAYERS/PLAYER[player.ID=6 or player.ID=2]">

And this will give me only the player.ID tags with the value of 6 or 2

Howerver, what I really need to do is this:

Code:
<xsl:for-each select="PLAYERS/PLAYER[$MyPARAM]">

This is due to the fact that my number of conditions may vary and come from the previous page's form.

How do I make $MyPARAM be interpreted as a condition insteal of a single value?
 
XSL is meant to work with nodesets. Passing a lot of info in a string requires you to take the string apart, wich is something xsl is not realy good for: it is not a progamming language. I strongly recommend that you look for a way to pass a nodeset to your stylesheet.
That being said: nothing is impossible, even if it is not advisable.
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
	<xsl:param name="Filter">
		<xsl:text>FILTER=ID=1|ID=76|ID=5|ID=45</xsl:text>
	</xsl:param>
	
	<xsl:template match="/">
		<xsl:call-template name="ParseFilterdItem">
			<!-- remove white-space -->
			<xsl:with-param name="FilterString" select="translate($Filter,' ','')"/>
		</xsl:call-template>
	</xsl:template>

	<xsl:template name="ParseFilterdItem">
		<xsl:param name="FilterString"/>
		<!-- get everything after the first 'ID='  -->
		<xsl:variable name="RightPart" select = "substring-after($FilterString,'ID=')"/>
		<xsl:variable name="id">
			<xsl:choose>
				<xsl:when test="contains($RightPart,'|')">
					<!-- take the part before '|' -->
					<xsl:value-of select = "substring-before($RightPart,'|')"/>
				</xsl:when>
				<xsl:otherwise>
					<!-- at the end of the original filterstring -->
					<xsl:value-of select = "$RightPart"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>

		<!-- use the id to parse nodes -->
		<xsl:apply-templates select="//PLAYERS/PLAYER[players.ID = $id]"/>

		<xsl:if test="contains($RightPart,'|')">	
			<!-- there is more to come, so parse the rest of the filterstring -->
			<xsl:call-template name="ParseFilterdItem">
				<xsl:with-param name="FilterString" select="$RightPart"/>
			</xsl:call-template>
		</xsl:if>
	
	</xsl:template>

	<xsl:template match="PLAYER">
		<xsl:value-of select="NAME_LAST"/>
	</xsl:template>

</xsl:stylesheet>
[code]
 
Maybe I am going about this all wrong.

Here is a link to my XML

What I want to be able to do is allow users, on the previous page, to select the week number(s), season(s), and players(s) to view side by side. This would be used to compare the stats of one week to another.

Would you have any other suggestions for this? If I would have been able to dyanmically achieve this:
Code:
<xsl:for-each select="PLAYERS/PLAYER[player.ID=6 or player.ID=2]">
Then I would have had no problem.

I appologize, Jel, as I did not specify this. What this means is that your code would list out all matching ID first. I would probably have to re-arrange it. Is there a more efficient way?

 
The stylesheet I posted can be used dynamically: when you parse it you can overwrite the param (I left the string I used to test, but you can remove it).
The way to fill-in the param(s) depends a bit on how you do the transformation.

Here's just an example in javascript:
Code:
<script type="text/javascript">

	var xslt = new ActiveXObject("Msxml2.XSLTemplate");
	var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
	var xslProc;
	var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
	var xmlParams = new ActiveXObject("Msxml2.DOMDocument");

	xmlDoc.async = false;
	xmlDoc.load("[URL unfurl="true"]http://www.bonticus.com/softball/XML/Data/SOFTBALL_WEEKS_STATS.xml");[/URL]
	xslDoc.async = false;
	xslDoc.load("C:\\Temp\\test.xsl");
	xslt.stylesheet = xslDoc;

	xmlParams.loadXML("<IDs><ID>1</ID><ID>2</ID><ID>3</ID></IDs>");

	xslProc = xslt.createProcessor();
	xslProc.input = xmlDoc;
	xslProc.addParameter("IDs", xmlParams.documentElement );
	xslProc.transform();
	document.write (xslProc.output);

</script>
As you can see, I passed an xml-node, not a string.
You can easily parse in xsl:

Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
   <xsl:output method="html" encoding="Windows-1252" />

   <xsl:param name="IDs" />

   <xsl:template match="/">
      <xsl:for-each select="//PLAYER[players.ID=$IDs/*]">
         <xsl:value-of select="NAME_LAST" />
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>
 
OK, I see how I could easy create a list of nodes. I can essentiall crate this:

Code:
<FDATA>
<YEAR>2004</YEAR>
<SEASON>SPRING</SEASON>
<WEEK>1</WEEK>
</FDATA>
<FDATA>
<YEAR>2004</YEAR>
<SEASON>SPRING</SEASON>
<WEEK>2</WEEK>
</FDATA>
...

This is very simple in the vbscript. Now My main XML is in a form of:
Code:
<comparisons>
<compare>
  <YEAR />
  <SEASON />
  <WEEK />
  ..
</compare>
<compare />
...
</comparisons>

How would you suggest that I set it up to filter and display only each compare node set that matches all three fields of the passed fdata nodeset?

Syntax of the for-each statement that would allow me to compare all three values?

Thank you for all your help..

 
Thi issue is just about closed. Thank you Jel, you deserve a star for waking me up on a few things.

First of all, your help on creating a node list and passing it works like a charm, Here is an example of doing it for all values:

HERE

I had also at one time successful wrote the ASP to convert the original XML to another XML doc, and then passed through to a transform doc to change to HTML; however, I still had some limitations and the server side work had to be tremendous.

My final problem deals with "grouping". I have added 4 sort lines after the for-each:

Code:
<xsl:for-each select="//weeknplayer[compareID=$IDs/*]">
<xsl:sort select="YEAR" order="ascending" data-type="number" />
<xsl:sort select="TRIMESTER" order="ascending" data-type="text" />
<xsl:sort select="WEEKNUMBER" order="ascending" data-type="number" />
<xsl:sort select="*[name()=$SortField]" order="{$SortOrder}" data-type="{$DataType}" />

This creates output such as:

SUMMER 2002 Week 1 Healy,Mike 4 ...
SUMMER 2002 Week 1 Tierney,Brandt 3 ...
SUMMER 2002 Week 2 Healy,Shawn 5 ...
SUMMER 2002 Week 2 Flatbush,Nick 6 ...

NOw I would like to add a header for each time the SUMMER, 2002, or Week number would change. I have tried this:

Code:
<xsl:if test="preceding-sibling::weeknplayer[1]/compareID != compareID">
	<tr>
		<td><xsl:value-of select="YEAR"/></td>
		<td><xsl:value-of select="TRIMESTER"/></td>
		<td colspan="2"><xsl:value-of select="WEEKNUMBER"/></td>
 	</tr>
</xsl:if>

But it doesn't seem to apply itself on the output, but during the processing, which is influenced by the sort, or it is to strictly based on node positioning, which isn't what actually prints out.

Any ideas folks. At current I am thinking I need to go back to a dual process, which would allow me to re-order the XML on the first process, and then the physical pressence check would work on the second (I think). But this would not be desired as such.
 
This issue is now closed, If I knew how to change my email address I would to be notified. I altered the XML to have all 3 fields in one element, and then to compare the single. This ultimately allowed for ordering as well. www.bonticus.com/fockers/

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top