无法在xsl:value-of select

时间:2018-05-15 13:00:31

标签: xslt xslt-1.0

我的部分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 &gt;= '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>

What i want to get

What i get

1 个答案:

答案 0 :(得分:0)

我发现这个XSLT存在两个问题(问题标记为&#39; xquery&#39;,我已经纠正了这个问题,两者都是不同的技术)。

a)在XML中,每个节点都有唯一的标识。因此,比较两个属性节点会导致他们的身份被比较,而不是他们的值。

//country[@id = @country]/name

表示处理器测试属性节点@id是否与属性节点@country具有相同的标识,即false。它就像有两辆车,每辆有4名乘客,但一辆车是丰田,另一辆是梅赛德斯。丰田不是梅赛德斯,即使两辆都载4名乘客。即使两者都是相同型号/车型/系列的丰田车,也不会匹配,因为即使两辆相同型号的车仍然是两辆不同的车。

b)排序相对于应用 on 返回的结果,即匹配的//city元素节点的所有子节点,因此{ {1}}属性必须考虑到这一点。

我已经解决了第一个问题(a),简化了select name的解决方法,只需将其作为XPath表达式,将节点层次结构向上移动两级。只要您处理的所有country个节点具有相同的结构,这都可以。

对于第二个问题(b)我已经应用了从模板中获得的排序键的相对位置,即相对于结果树片段(我假设,您希望按降序排序所有国家/地区) ,以及一个国家内所有匹配的城市都在上升。)

country

XSLT样式表的另一种替代方法是所谓的&#34; push&#34;方法(与此处使用的&#34; pull&#34;方法相反),其中一个为XML文件中的所有兴趣点声明模板,然后让处理器遍历每个模板,匹配匹配。这很方便,特别是在创建复杂变换时。

<?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 &gt;= '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>

更重要的是,最后一个模板可以写成

<?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 &gt;= '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 &gt;= '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处理器只是应用它的built-in templates,在这种情况下只需取节点的值并将其插入给定位置的result tree。另请参阅"Push, Pull, Next!" by Bob DuCharme"Push vs. Pull" on the XSL FAQ以及Eddie Welker的简短介绍"Advantages of push-style XSLT over pull-style",了解此方法的概述。