我的xml的一部分:
<mondial>
<country id="f0_967" name="United States" capital="f0_1970" population="266476272" datacode="US" total_area="9372610" population_growth="0.91" infant_mortality="6.7" gdp_agri="2" gdp_total="7247700" inflation="2.5" indep_date="04 07 1776" government="federal republic" gdp_ind="23" gdp_serv="75" car_code="USA">
<name>USA</name>
............
<province id="f0_19685" name="Alaska" country="f0_967" capital="f0_15543" population="609311" area="1530694">
<city id="f0_14626" country="f0_967" province="f0_19685" longitude="-150.017" latitude="61.1667">
<name>Anchorage</name>
</city>
</province>
...........
</country>
</mondial>
基本上,我想获取高于一定纬度的城市并按国家/地区对其进行排序,但我什至无法正确显示国家/地区。
我目前的 .xsl:
<?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="/mondial/country/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="//country[@id = @country]/name"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
我想得到什么
我得到什么
我看到这个 XSLT 有两个问题(这个问题被标记为"xquery",我已经纠正了这一点,两者都是不同的技术(。
a( 在 XML 中,每个节点都有一个唯一的标识。因此,比较两个属性节点会导致比较它们的标识,而不是它们的值。
//country[@id = @country]/name
表示,处理器测试属性节点@id
是否与属性节点@country
具有相同的标识,即false
。这就像有两辆车,每辆车有 4 名乘客,但一辆车是丰田,另一辆车是梅赛德斯。丰田不是梅赛德斯,即使两者都载有 4 名乘客。即使两者都是相同型号/制造年份/系列的丰田汽车,这也不匹配,因为即使是两辆相同型号的汽车仍然是两辆不同的汽车。
b( 排序相对于返回结果应用,返回结果是匹配//city
元素节点的所有子节点,因此select
属性必须考虑到这一点。
我已经解决了第一个问题 (a( 通过简化解决country
name
的方法,只需将其视为 XPath 表达式,该表达式将节点层次结构向上移动两级。只要您处理的所有country
节点具有相同的结构,这将起作用。
对于第二个问题 (b(,我应用了排序键的相对位置,即相对于您从模板中获得的结果树片段(我假设您希望按降序对所有国家/地区进行排序,以及国家/地区内的所有匹配城市升序(。
<?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>
XSLT 样式表的另一种替代方法是所谓的"push"方法(与此处使用的"pull"方法相反(,其中为 XML 文件中的所有关注点声明模板,然后让处理器逐个匹配地处理这些模板中的每一个。这很方便,尤其是在创建复杂的转换时。
<?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>
更重要的是,最后一个模板本可以写出来
<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>
因为 XSL 处理器只是应用其内置模板,在这种情况下,这些模板只是获取节点的值并将其插入到给定位置的结果树中。另请参阅Bob DuCharme的"Push, Pull, Next!",XSL FAQ上的"Push vs. Pull",以及Eddie Welker的非常好的简短介绍,"Advantage of push-style XSLT over pull-style",了解此方法的概述。