не может фильтровать внутри xsl: value-of select - PullRequest
0 голосов
/ 15 мая 2018

Часть моего 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>

Что я хочу получить

Что я получу

1 Ответ

0 голосов
/ 12 июня 2018

Я вижу две проблемы с этим XSLT (вопрос был помечен как 'xquery', я исправил это, обе технологии разные).

a) В XML каждый узел имеет уникальную идентичность.Поэтому сравнение двух узлов атрибута приводит к сравнению их значений, а не их значений.

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

означает, что процессор проверяет, имеет ли узел атрибута @id такую ​​же идентичность, что и узел атрибута @country, что составляет false.Это как две машины, по 4 пассажира в каждой, но одна машина - Toyota, а другая - Mercedes.Тойота не Мерседес, даже если оба перевозят 4 пассажиров.Даже если бы оба были Тойотами одной и той же модели / года выпуска / серии, это не совпало бы, так как даже два автомобиля одной и той же модели по-прежнему являются двумя разными автомобилями. и на возвращенный результат, который является всеми дочерними элементами соответствующих узлов элемента //city, поэтому атрибут select должен учитывать это.

Я обратилсяпервая проблема (а), упрощая способ обращения к name из country, просто принимая его как выражение 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 &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>

Другой альтернативный метод дляВаша таблица стилей 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 &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:template match="city[@latitude &gt;= '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 просто применяет его встроенные шаблоны , которые в этом случае просто принимают значение узла и вставляют его в результирующее дерево в заданной позиции.Смотри также «Тяни, Тяни, Дальше!»Боб Дюшарм , "Push vs. Pull" в XSL FAQ и очень приятное, краткое введение Эдди Уэлкера, "Преимущества XSLT в стиле push по сравнению с pull-style" для обзора этого метода.

...