Why won't this for-each loop work?

M

Mark Constant

I have a xslt file and it keeps giving me an EOF error when it reaches
the point
<xsl:for-each select="lc:Entertainment/lc:$Hardware[lc:Genre =
$Genre]">
and
<xsl:for-each select="lc:Entertainment/lc:$Hardware">

My xslt file looks like this
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lc="http://mark/Homepage/">
<xsl:eek:utput method="html"/>
<xsl:param name="Hardware"/>
<xsl:param name="Genre"/>

<xsl:template match="/">
<xsl:choose>
<xsl:when test="$Genre = 'All'">
<xsl:call-template name="All" />
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name="NotAll" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template name="All">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:$Hardware">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:$Hardware[lc:Genre =
$Genre]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

</xsl:stylesheet>

My xml file looks like this
<Entertainment xmlns="http://mark/Homepage/">
<Movie>
<Title>Terminator 1</Title>
<Description>A T100 machine comes back from the future to destroy
Sarah Connor who will give birth to a kid who will go on to save the
world.</Description>
<Genre>Action</Genre>
<Picture>images\movies\Terminator1.jpg</Picture>
<Rating>5</Rating>
</Movie>
<Movie>
<Title>Terminator 2</Title>
<Description>The T100 is back again only this time he is back to
save John Connor from a T1000</Description>
<Genre>Action</Genre>
<Picture>images\movies\Terminator2.jpg</Picture>
<Rating>5</Rating>
</Movie>
<PS2>
<Title>Mortal Kombat Deadly Alliance</Title>
<Description>Quan Chi and Shang Tsung join forces to destroy Lui
Kang and take over the wrold</Description>
<Genre>Fighting</Genre>
<Picture>images\ps2\MortalKombat.jpg</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Sly Cooper</Title>
<Description>A racoon must travel around the world to get back
pieces of a book that has been in his family for
generations</Description>
<Genre>Platformer</Genre>
<Picture>images\ps2\SlyCooper</Picture>
<Rating>5</Rating>
</PS2>
</Entertainment>

I am passing my variable through a piece of Javascript code that looks
like this
xsltProc.addParameter("Hardware", Hardware);
xsltProc.addParameter("Genre", SelValue);
 
D

Dimitre Novatchev

Mark Constant said:
I have a xslt file and it keeps giving me an EOF error when it reaches
the point
<xsl:for-each select="lc:Entertainment/lc:$Hardware[lc:Genre =
$Genre]">
and
<xsl:for-each select="lc:Entertainment/lc:$Hardware">

This is not legal.

lc:$Hardware is not a QName.

Probably you wanted:

lc:*[local-name() = $Hardware]

or (,which is the same):

*[name() = concat('lc:', $Hardware)]



=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
M

Mark Constant

I am still getting an error saying that Hardware is undefined. All I
want is a drop down list. If the user is on the PS2 page it will send
the parameter PS2 for Hardware and then whatever Genre they selected.
Here is what I changed my XSLT code to
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lc="http://mark/Homepage/">
<xsl:eek:utput method="html"/>
<xsl:param name="Hardware"/>
<xsl:param name="Genre"/>

<xsl:template match="/">
<xsl:choose>
<xsl:when test="$Genre = 'All'">
<xsl:call-template name="All" />
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name="NotAll" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template name="All">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>

My Javascript code looks like this
function CallXML(dropdown, hardware)
{
var myIndex = dropdown.selectedIndex;
var SelValue = dropdown.options[myIndex].value;
var xsltTree = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
xsltTree.async = false;
xsltTree.load("Entertainment.xslt")

var srcTree = new ActiveXObject("Msxml2.DOMDocument.4.0");
srcTree.async = false;
srcTree.load("Entertainment.xml");

var xsltThread = new ActiveXObject("Msxml2.XSLTemplate.4.0");
xsltThread.stylesheet = xsltTree;
var xsltProc = xsltThread.createProcessor();
xsltProc.input = srcTree;
xsltProc.addParameter("Hardware", Hardware);
xsltProc.addParameter("Genre", SelValue);


xsltProc.transform();
GameTable.innerHTML = xsltProc.output;
}
 
D

Dimitre Novatchev

Mark Constant said:
I am still getting an error saying that Hardware is undefined.

This is not a Javascript group. The error is in your script -- see below.
All I
want is a drop down list. If the user is on the PS2 page it will send
the parameter PS2 for Hardware and then whatever Genre they selected.
Here is what I changed my XSLT code to
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lc="http://mark/Homepage/">
<xsl:eek:utput method="html"/>
<xsl:param name="Hardware"/>
<xsl:param name="Genre"/>

<xsl:template match="/">
<xsl:choose>
<xsl:when test="$Genre = 'All'">
<xsl:call-template name="All" />
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name="NotAll" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template name="All">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>

My Javascript code looks like this
function CallXML(dropdown, hardware)
{
var myIndex = dropdown.selectedIndex;
var SelValue = dropdown.options[myIndex].value;
var xsltTree = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
xsltTree.async = false;
xsltTree.load("Entertainment.xslt")

var srcTree = new ActiveXObject("Msxml2.DOMDocument.4.0");
srcTree.async = false;
srcTree.load("Entertainment.xml");

var xsltThread = new ActiveXObject("Msxml2.XSLTemplate.4.0");
xsltThread.stylesheet = xsltTree;
var xsltProc = xsltThread.createProcessor();
xsltProc.input = srcTree;
xsltProc.addParameter("Hardware", Hardware);

You don't have a variable named "Hardware" defined in your Javascript code.
The line above will raise an error due to this.
 
M

Mark Constant

I fixed the Javascript error easy enough once I noticed my mistake.
Now I get an error that seems to be a FAQ that reads "Reference to
variable or parameter 'Hardware' must evaluate to a node set list. Now
from what I have been reading I have to add a function called
node-set() but where I need to add it is what I can't figure out. Here
is my XSLT code.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lc="http://mark/Homepage/">
<xsl:eek:utput method="html"/>
<xsl:param name="Hardware"/>
<xsl:param name="Genre"/>

<xsl:template match="/">
<xsl:choose>
<xsl:when test="$Genre = 'All'">
<xsl:call-template name="All" />
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name="NotAll" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template name="All">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
 
D

Dimitre Novatchev

Mark Constant said:
I fixed the Javascript error easy enough once I noticed my mistake.
Now I get an error that seems to be a FAQ that reads "Reference to
variable or parameter 'Hardware' must evaluate to a node set list. Now
from what I have been reading I have to add a function called
node-set() but where I need to add it is what I can't figure out. Here
is my XSLT code.


using the xxx:node-set() extension function won't help.

From your code it can be seen that in different places you're using
the value of the "Hardware" parameter both as a simple value (string)
and as a node-set.

Most probably you're passing a string as the value of the "Hardware"
parameter.

However in the "NotAll" template you're using it as a node-set:
<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">

BTW the above hardly makes sense to me. What did you really want?
Please, say it with words.

Probably your problem is here and you have to correct it.

Anyway, should you continue to use the same parameter supposing it has
two different types at the same time, the solution is to use two
different parameters -- one string and one node-set.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL







<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lc="http://mark/Homepage/">
<xsl:eek:utput method="html"/>
<xsl:param name="Hardware"/>
<xsl:param name="Genre"/>

<xsl:template match="/">
<xsl:choose>
<xsl:when test="$Genre = 'All'">
<xsl:call-template name="All" />
</xsl:when>
<xsl:eek:therwise>
<xsl:call-template name="NotAll" />
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<xsl:template name="All">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
 
M

Mark Constant

I can see now that the problem lies within the NotAll template. It
will take a little while to explain in words but here I go. I have an
xml file that supports three types of hardware PS2, XBOX, and Movie.
Now if the user is on the PS2 and selects that they want the genre
horror it will send two parameters. One being the Hardware (i.e. PS2)
and then the Genre which is horror. From there the template calls
NotAll and says for every instance of PS2 in the XML that has a Genre
of horror then display it. Here is my Xslt again.
<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">
<tr>
<th colspan="2" bgcolor="Green"><xsl:value-of
select="lc:Title"/></th>
</tr>
<tr>
<td>
<xsl:element name="IMG">
<xsl:attribute name="SRC">
<xsl:value-of select="lc:picture"/>
</xsl:attribute>
</xsl:element>
</td>
<td>
<xsl:value-of select="lc:Description"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

It is obvious that I need to change <xsl:for-each
select="lc:Entertainment/lc:*[local-name() = $Hardware[lc:Genre =
$Genre]]"> but what I need to change it to is what I am wondering.
Basically I want this line to say whatever Hardware the user pass
display the xml content only if the genre is horror. Here is an
example of my xml file.

<Entertainment xmlns="http://mark/Homepage/">
<PS2>
<Title>Grand Theft Auto 3</Title>
<Description>An open ended enviroment where you have to take on jobs
for different mob bosses to stay alive</Description>
<Genre>TPA</Genre>
<Picture>images\ps2\GrandTheftAuto3.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Maximo</Title>
<Description>After returning from a war you find out that you must
save the love of your life from your one time friend turned
nemesis</Description>
<Genre>Platformer</Genre>
<Picture>images\ps2\Maximo.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Mortal Kombat Deadly Alliance</Title>
<Description>Quan Chi and Shang Tsung join forces to destroy Lui
Kang and take over the world</Description>
<Genre>Fighting</Genre>
<Picture>images\ps2\MortalKombat.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Ratchet and Clank</Title>
<Description>In this action platformer you must play as a Cat and
Robot team that must work together to save the world from the evil
Chairman Drek</Description>
<Genre>Platformer</Genre>
<Picture>images\ps2\RatchetAndClank.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Silent Hill 2</Title>
<Description>After recieving a letter from a wife who you thought
was dead you travel to a huanted town to find out the
truth</Description>
<Genre>Horror</Genre>
<Picture>images\ps2\SilentHill2.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Sly Cooper</Title>
<Description>A racoon must travel around the world to get back
pieces of a book that has been in his family for
generations</Description>
<Genre>Platformer</Genre>
<Picture>images\ps2\SlyCooper.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>The Getaway</Title>
<Description>You play as Mark Hammond who is taken back into the mob
life to save the life of his own child</Description>
<Genre>Platformer</Genre>
<Picture>images\ps2\TheGetaway.gif</Picture>
<Rating>5</Rating>
</PS2>
<PS2>
<Title>Tribes: Ariel Assualt</Title>
<Description>This game is a port of a old PC game where you can fly
using jetpacks but also use vehicles</Description>
<Genre>FPS</Genre>
<Picture>images\ps2\Tribes.gif</Picture>
<Rating>3</Rating>
</PS2>
<PS2>
<Title>Virtua Fighter 4: Evolution</Title>
<Description>Travel around the world to fight A.I. that is
programmed after the best Virtua Fighter arcade players</Description>
<Genre>Fighting</Genre>
<Picture>images\ps2\NoGif.gif</Picture>
<Rating>5</Rating>
</PS2>
</Entertainment>
 
D

Dimitre Novatchev

Mark Constant said:
I can see now that the problem lies within the NotAll template. It
will take a little while to explain in words but here I go. I have an
xml file that supports three types of hardware PS2, XBOX, and Movie.
Now if the user is on the PS2 and selects that they want the genre
horror it will send two parameters. One being the Hardware (i.e. PS2)
and then the Genre which is horror. From there the template calls
NotAll and says for every instance of PS2 in the XML that has a Genre
of horror then display it. Here is my Xslt again.
<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">

You didn't understand the pattern -- one cannot use a string as a node-set.

Also the above doesnt make sense -- if $Hardware were a node-set it would
mean:

Select all children of lc:Entertainment that are in the namespace to which
the prefix "lc" is bound and that have local-name the same as the *value* of
the (first node of) the node=set of all nodes belonging to $Hardware, which
have an lc:Genre child with value $Genre

As in the previous template, once again, you have to write:

<xsl:for-each
select="lc:Entertainment/lc:*[local-name() = $Hardware][lc:Genre =
$Genre]]">



I think that using the XPath Visualizer may be very helpful in such cases as
it has been proven in practice to be an effective XPath learning tool.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
M

Mark Constant

Dimitre Novatchev said:
Mark Constant said:
I can see now that the problem lies within the NotAll template. It
will take a little while to explain in words but here I go. I have an
xml file that supports three types of hardware PS2, XBOX, and Movie.
Now if the user is on the PS2 and selects that they want the genre
horror it will send two parameters. One being the Hardware (i.e. PS2)
and then the Genre which is horror. From there the template calls
NotAll and says for every instance of PS2 in the XML that has a Genre
of horror then display it. Here is my Xslt again.
<xsl:template name="NotAll">
<table border="0">
<xsl:for-each select="lc:Entertainment/lc:*[local-name() =
$Hardware[lc:Genre = $Genre]]">

You didn't understand the pattern -- one cannot use a string as a node-set.

Also the above doesnt make sense -- if $Hardware were a node-set it would
mean:

Select all children of lc:Entertainment that are in the namespace to which
the prefix "lc" is bound and that have local-name the same as the *value* of
the (first node of) the node=set of all nodes belonging to $Hardware, which
have an lc:Genre child with value $Genre

As in the previous template, once again, you have to write:

<xsl:for-each
select="lc:Entertainment/lc:*[local-name() = $Hardware][lc:Genre =
$Genre]]">



I think that using the XPath Visualizer may be very helpful in such cases as
it has been proven in practice to be an effective XPath learning tool.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL

Dang your good at this stuff. Thanks once again. That worked perfectly.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top