PDA

View Full Version : Displaying by attribute via XPath


Erich
11-22-2003, 07:21 AM
My XML file looks basicaly like this:


<tour>
<year id="2001">
<show id="20010507">
<date>05/07/01 (A)</date>
<artist>Tim Solo</artist>
<location>
<venue>The Wetlands</venue>
<city>New York City</city>
<state>NY</state>
</location>
</show>
</year>
<year id="2003">
<show id="20030227" status="canceled">
<date>02/27/03</date>
<artist>Tim Solo (A)</artist>
<location>
<venue>32 Bleu</venue>
<city>Colorado Springs</city>
<state>CO</state>
</location>
</show>
<show id="20030228" status="canceled">
<date>02/28/03</date>
<artist>Tim Solo (A)</artist>
<location>
<venue>Bluebird Theater</venue>
<city>Denver</city>
<state>CO</state>
</location>
</show>
<show id="20030301" status="canceled">
<date>03/01/03</date>
<artist>Tim Solo (A)</artist>
<location>
<venue>Fox Theater</venue>
<city>Boulder</city>
<state>CO</state>
</location>
</show>
</year>
</tour>


and this is what my XSL file basically looks like:


<xsl:template match="/tour/year[@id='2001']">
<html>
<head>
<title>Tour: <xsl:value-of select="@id" /></title>
<LINK REL="stylesheet" HREF="../pps.css" TYPE="text/css" />
</head>
<body bgcolor="#000000">
<table Border="1" bordercolor="#444444" align="center" width="98%">
<thead>
<tr>
<th width="10%">Date</th>
<th width="20%">Artist</th>
<th width="60%">Venue</th>
<th width="10%">Show Info</th>
</tr>
<tr>
<td colspan="4">.</td>
</tr>
</thead>
<tbody>
<xsl:apply-templates />
</tbody>
</table>
<br />
<br />
</body>
</html>
</xsl:template>

<xsl:template match="/tour/year/show">
<tr>
<td align="center"><xsl:value-of select="date" /></td>
<td align="center"><xsl:value-of select="artist" /></td>
<td align="center"><xsl:value-of select="location/venue" />: <xsl:value-of select="location/city" />, <xsl:value-of select="location/state" /></td>
<td align="center">Info</td>
</tr>
</xsl:template>


when i go to display this, it filters the proper content into the table, but then prints all the other content in the xml file as text outside the table. I want to be able to filter the information in the xsl file via attribute in the xml file to show up in the table and have all the other information not shown. Am I doing something wrong?

Any help is apprectiated, thanks :)

M@rco
11-23-2003, 05:47 PM
I seem to recall that this was a bug in a particular XML parser (MSXML3 perhaps), which is resolved by including a "catch-all" template element like this:<xsl:template match="*" />However, I may be wrong. ;)

Erich
11-24-2003, 05:14 AM
Didnt work :(. I included that in my xsl page and it causes the entire output page to come up blank.

Any other suggestions? Or for that matter, any other XML parsers I can use that are more standard and less buggy?

M@rco
11-24-2003, 11:03 AM
Firstly, make sure you put that template element after all the others, not at the start.

And secondly, you haven't said which XML parser you ARE using!

:p

Erich
11-24-2003, 07:55 PM
yup, i put it after the last template and it didnt work:


<xsl:template match="/tour/year/show">
<tr>
<td align="center">
<xsl:value-of select="date"/>
</td>
<td align="center">
<xsl:value-of select="artist"/>
</td>
<td align="center">
<xsl:value-of select="location/venue"/>: <xsl:value-of select="location/city"/>, <xsl:value-of select="location/state"/>
</td>
<td align="center">Info</td>
</tr>
</xsl:template>

<xsl:template match="*" />

</xsl:stylesheet>


and sorry, Im using IE, but Mozilla Firebird and the built in parser for XMLSpy also had the same problem.

M@rco
11-24-2003, 08:16 PM
Originally posted by Erich
Im using IE, but Mozilla Firebird and the built in parser for XMLSpy also had the same problem. Then you're making a basic mistake somewhere. Please post the full XML input file (or at least a representative slimmed-down version if it's too big), and the full XSLT file.

Erich
11-24-2003, 08:30 PM
Originally posted by M@rco
Then you're making a basic mistake somewhere. Please post the full XML input file (or at least a representative slimmed-down version if it's too big), and the full XSLT file.

sure thing (im truncating most of the xml file, the show sections are the same all the way down):


<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="tour.xsl"?>
<tour>
<year id="2001">
<show id="20010507">
<date>05/07/01</date>
<artist>Tim Solo</artist>
<location>
<venue>The Wetlands</venue>
<city>New York City</city>
<state>NY</state>
</location>
<information>
<setlist>
<set type="1">
<song>Stanger In A Strained Land</song>
<song>Do It Yourself</song>
<song>Flourescence</song>
<song>Frogs of Doom</song>
<song>Decline In Reason</song>
<song>Hopeful Heresy</song>
<song>Dissident</song>
<song>Squishy Moans</song>
<song>Big Blast Of Hot Air</song>
<song notes="segue">Letting Go</song>
<song>As Far As We Can See</song>
<song>Try A Little Harder</song>
<song>High In The West</song>
<song>Insect Repellant Mouthwash</song>
<song>You Are My Sanity</song>
<song>Jemez Rolling Waves</song>
<song>Loose Interpretations</song>
<song>Banana Splitz Sh-ts</song>
</set>
<set type="e">
<song>Defamation Of Character</song>
</set>
</setlist>
</information>
</show>
</year>
<year id="2003">
<show id="20030227" status="canceled">
<date>02/27/03</date>
<artist>Tim Solo (A)</artist>
<location>
<venue>32 Bleu</venue>
<city>Colorado Springs</city>
<state>CO</state>
</location>
</show>
<show id="20030228" status="canceled">
<date>02/28/03</date>
<artist>Tim Solo (A)</artist>
<location>
<venue>Bluebird Theater</venue>
<city>Denver</city>
<state>CO</state>
</location>
</show>
.
.
.
<show id="20030228">
<date>09/28/03</date>
<artist>Tim Solo (A/E)</artist>
<location>
<venue>Point</venue>
<city>Bryn Mawr</city>
<state>PA</state>
</location>
</show>
</year>
</tour>


xsl:


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/tour/year[@id='2003']">
<html>
<head>
<title>Tour: <xsl:value-of select="@id"/>
</title>
</head>
<body>
<table border="1" align="center" width="98%">
<thead>
<tr>
<th width="10%">Date</th>
<th width="20%">Artist</th>
<th width="60%">Venue</th>
<th width="10%">Show Info</th>
</tr>
<tr>
<td colspan="4">.</td>
</tr>
</thead>
<tbody>
<xsl:apply-templates/>
</tbody>
</table>
<br/>
<br/>
</body>
</html>
</xsl:template>

<xsl:template match="/tour/year/show">
<tr>
<td align="center">
<xsl:value-of select="date"/>
</td>
<td align="center">
<xsl:value-of select="artist"/>
</td>
<td align="center">
<xsl:value-of select="location/venue"/>: <xsl:value-of select="location/city"/>, <xsl:value-of select="location/state"/>
</td>
<td align="center">Info</td>
</tr>
</xsl:template>

</xsl:stylesheet>

M@rco
11-24-2003, 09:59 PM
What's the output you get, and what's the output you want?

Erich
11-24-2003, 11:06 PM
Originally posted by M@rco
What's the output you get, and what's the output you want?

the output im looking for is this:

http://erichwithanh.com/tim/tour/2003.html

Right now im just trying to figure out how to get it to filter correctly, though. In the end, I want to be able to set up a php page that allows for the information to be dynamicaly rendered as per the url.

the output im getting though, if i were to try and filter for 2001 in my example, would be this:

http://www.erichwithanh.com/xml.gif

Again, im just working on the filtering so the styling can be added later. I just want it to filter without still including the other information.

Erich
11-25-2003, 12:16 AM
While I'm at it, i might as well extend my question slightly. If i wanted to add CANCELED text next to a shows location, would this be the proper way to do it, using the same xsl file:


<xsl:template match="/tour/year/show">
<tr>
<td align="center">
<xsl:value-of select="date"/>
</td>
<td align="center">
<xsl:value-of select="artist"/>
</td>
<td align="center">
<xsl:value-of select="location/venue"/>: <xsl:value-of select="location/city"/>, <xsl:value-of select="location/state"/>
<xsl:if test="show[@status] = canceled">
(CANCELED)
</xsl:if>
</td>
<td align="center">Info</td>
</tr>
</xsl:template>

M@rco
11-25-2003, 12:39 AM
Well, while you're at it, why don't you make use of your copy of XMLSpy to step through the XSLT yourself and see why it's going wrong?

;)

Erich
11-25-2003, 01:41 AM
Originally posted by M@rco
Well, while you're at it, why don't you make use of your copy of XMLSpy to step through the XSLT yourself and see why it's going wrong?

;)

Since I downloaded it on a whim the other day to see if it would parse differently, im no expert at it, but upon going through the XSLT Debugger I realized how its processing the file. The second template in my XSL file gets processed first. So whatever comes before or after the year I dont filtered out of the file gets processed before or after my html tags, causing it to show up the way it does.

I'll experiment with the file and other oporations, but any information as to WHY the second template in the file gets processed first and anything I can do to change that would be fantastic. Im doing my best to learn this, but I dont see anything inherantly wrong with my document or concept (unless its pointed out), just my lack of knowledge on the internal process involved combining the two.

EDIT:

After spending some more time fiddling with it, they work fine together now. Heres my slightly updated XSLT file (with small tweaks from tinkering with the XML file):


<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="year"><xsl:value-of select="tour/year[@id='2001']/@id"/></xsl:variable>

<xsl:template match="/">
<html>
<head>
<title>Tour: <xsl:value-of select="$year"/>
</title>
</head>
<body>
<table border="1" width="100%" height="23%">
<tr>
<td align="center"><img src="{$year}head.gif" /></td>
</tr>
</table>
<br />
<br />
<table Border="1" align="center" width="98%">
<thead>
<tr>
<th width="10%">Date</th>
<th width="20%">Artist</th>
<th width="60%">Venue</th>
<th width="10%">Show Info</th>
</tr>
<tr>
<td colspan="4">.</td>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="tour"/>
</tbody>
</table>
<br/>
<br/>
</body>
</html>
</xsl:template>

<xsl:template match="tour">
<xsl:for-each select="year[@id='2001']/show">
<tr>
<td align="center">
<xsl:value-of select="date/@id"/>
</td>
<td align="center">
<xsl:value-of select="artist"/>
</td>
<td align="center">
<xsl:value-of select="location/venue"/>: <xsl:value-of select="location/city"/>, <xsl:value-of select="location/state"/>
</td>
<td align="center"><a href="{@id}">Info</a></td>
</tr>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>


Now the only thing i need to figure out for this particular page is the "canceled" thing i mentioned earlier, thats giving me problems.

M@rco - thanks for your time, regardless of whether or not you directly helped. Still got my brain moving :p

M@rco
11-25-2003, 03:32 PM
You're welcome, glad you've managed to do it under your own steam... always more satisfying that way, isn't it? ;)

I think the bit you've added to handle cancelled shows should be fine, apart from the fact that you need to enclose your string in single quotes, like this:<xsl:if test="show[@status] = 'canceled'">

Does that work now?