I see two problems with this XSLT (the question was tagged with 'xquery', I have corrected this, both are different technologies).
a) In XML every node has a unique identity. Therefore comparing two attribute nodes results in their identity becoming compared, rather than their values.
//country[@id = @country]/name
means, that the processor tests whether the attribute node @id
is of same identity as the attribute node @country
, which is false
. It's like having two cars, with 4 passengers in each, but one car is a Toyota, the other one a Mercedes. A Toyota is not a Mercedes, even if both carry 4 passengers. Even if both were Toyotas of the same model/buildyear/series, this would not match, since even two of the same model cars still are two different cars.
b) The sorting gets applied relative to and on the returned result, which is all the children of the matching //city
element nodes, therefore the select
attribute must take this into account.
I have addressed the first issue (a) by simplifying the way to address the name
of the country
by just taking it as an XPath expression, that travels the node hierarchy up by two levels. This will work, as long as all country
nodes, you process, have the same structure.
For the second issue (b) I have applied the relative location of the sorting keys, that is, relative to the result tree fragment, that you get from the template (I assume, you want to sort all countries in descending order, and all matching cities within a country ascending).
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<body>
<h1 align="center">Mondial</h1>
<table border="1">
<tr bgcolor="blue">
<th>Ciutat</th>
<th>Latitud</th>
<th>Longtitud</th>
<th>Pais</th>
</tr>
<xsl:for-each select="//city[@latitude >= '41.4']">
<xsl:sort select="../../name" order="descending"/>
<xsl:sort select="name"/>
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="@longitude"/></td>
<td><xsl:value-of select="@latitude"/></td>
<td><xsl:value-of select="parent::province/parent::country/name"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Another, alternative, method for your XSLT stylesheet would be what is called the "push" method (in opposite to the "pull" method in use here), where one declares templates for all points of interest in the XML file, and then let the processor work through each of these templates, match by match. This comes handy, especially when one creates complex transforms.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head><title></title></head>
<body>
<table border="1">
<tr bgcolor="blue">
<th>Ciutat</th>
<th>Latitud</th>
<th>Longtitud</th>
<th>Pais</th>
</tr>
<xsl:apply-templates select="mondial/country/province/city[@latitude >= '41.4']">
<xsl:sort select="parent::province/parent::country/name" order="descending"/>
<xsl:sort select="name"/>
</xsl:apply-templates>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="city[@latitude >= '41.4']">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="@longitude"/></td>
<td><xsl:value-of select="@latitude"/></td>
<td><xsl:value-of select="../../name"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
Even more so, the last template could have been written
<xsl:template match="city[@latitude >= '41.4']">
<tr>
<td><xsl:apply-templates select="name"/></td>
<td><xsl:apply-templates select="@longitude"/></td>
<td><xsl:apply-templates select="@latitude"/></td>
<td><xsl:apply-templates select="../../name"/></td>
</tr>
</xsl:template>
since the XSL processor simply applies its built-in templates, which in this case simply take the value of the node and insert it into the result tree at the given position. See also "Push, Pull, Next!" by Bob DuCharme, "Push vs. Pull" on the XSL FAQ and a very nice, short introduction by Eddie Welker, "Advantages of push-style XSLT over pull-style" for an overview of this method.