xslt сортировка по количеству дочерних элементов - PullRequest
2 голосов
/ 20 ноября 2011

Я пытаюсь создать HTML-таблицу, запрашивая XML-документ. Я использую xslt.

Вот проблема. «родительский» узел содержит много «дочерних» узлов. Я должен о / п таблицы, которая содержит @ имя родителя и количество «дочерних» узлов в отсортированном порядке (по убыванию). Итак, я делаю

 <?xml version="1.0" encoding="ISO-8859-1"?>

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="parent[count(child) &gt; 3]">

  <html>
   <table border="1">
      <xsl:for-each select=".">
      <xsl:sort select="{count(child)}" data-type="number" order="descending"/>
        <tr>
        <td><b><xsl:value-of select="@name" /></b></td>
        <td><xsl:value-of select="count(child)" /></td>
        </tr>
      </xsl:for-each> 
   </table>
   </html>

   </xsl:template>
   <xsl:template match="text()" />
  </xsl:stylesheet>

Я получаю HTML, однако единственная проблема в том, что я не получаю его в отсортированном порядке по количеству дочерних элементов. Я подозреваю, что неправильно использую count xsl: sort? Вы можете помочь?

Ввод xml

<outer>
<parent name="abc" attr1="22664136" attr2="647500">
<child percentage="11">aaa</child>
<child percentage="35">bbb</child>
<child percentage="50">ccc</child>
</parent>

<parent name="ggg" attr1="3249136" attr2="28750"/>

<parent name="ghi" attr1="29183032" attr2="2381740">
<child2>
<name>ppp</name>
<attr1>1507241</attr1>
</child2>
</parent>


<parent name="qwe" attr1="10342899" attr2="1246700"/>

<parent name="lkj" attr1="65647" attr2="440">
<child percentage="100">jjj</child>
</parent>

</outer>

Ответы [ 3 ]

3 голосов
/ 21 ноября 2011

В предоставленном коде XSLT имеется множество ошибок!

Самая большая проблема здесь:

    <xsl:for-each select=".">
      <xsl:sort select="{count(child)}" data-type="number" order="descending"/>
      <tr>
        <td><b><xsl:value-of select="@name" /></b></td>
        <td><xsl:value-of select="count(child)" /></td>
      </tr>
    </xsl:for-each>

Это не будет выполнять какую-либо значимую сортировку, поскольку набор узлов сортируемых узлов содержит только один узел - текущий узел.

Следующая проблема здесь :

<xsl:sort select="{count(child)}" data-type="number" order="descending"/>

В атрибуте select инструкции XSLT не должно быть AVT - необходимо удалить фигурные скобки.

Третья проблема заключается в том, что сортировка указана слишком поздно - внутри шаблона используется parent. Родитель не имеет дочерних элементов, которые сами имеют child дочерних элементов.

Решение : Исправляя все основные проблемы, рассмотренные выше, можно получить следующий код:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/*">
        <html>
            <table border="1">
                <xsl:for-each select="parent">
                    <xsl:sort select="count(child)" data-type="number" order="descending"/>
                    <tr>
                        <td>
                            <b>
                                <xsl:value-of select="@name" />
                            </b>
                        </td>
                        <td>
                            <xsl:value-of select="count(child)" />
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </html>
    </xsl:template>
    <xsl:template match="text()" />
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<outer>
    <parent name="abc" attr1="22664136" attr2="647500">
        <child percentage="11">aaa</child>
        <child percentage="35">bbb</child>
        <child percentage="50">ccc</child>
    </parent>
    <parent name="ggg" attr1="3249136" attr2="28750"/>
    <parent name="ghi" attr1="29183032" attr2="2381740">
        <child2>
            <name>ppp</name>
            <attr1>1507241</attr1>
        </child2>
    </parent>
    <parent name="qwe" attr1="10342899" attr2="1246700"/>
    <parent name="lkj" attr1="65647" attr2="440">
        <child percentage="100">jjj</child>
    </parent>
</outer>

получается искомый результат :

<html>
   <table border="1">
      <tr>
         <td><b>abc</b></td>
         <td>3</td>
      </tr>
      <tr>
         <td><b>lkj</b></td>
         <td>1</td>
      </tr>
      <tr>
         <td><b>ggg</b></td>
         <td>0</td>
      </tr>
      <tr>
         <td><b>ghi</b></td>
         <td>0</td>
      </tr>
      <tr>
         <td><b>qwe</b></td>
         <td>0</td>
      </tr>
   </table>
</html>
1 голос
/ 20 ноября 2011

Почти.Вам не нужны фигурные скобки вокруг xsl:sort select="...". Тогда ваш for-each будет выглядеть так:

<xsl:for-each select=".">
  <xsl:sort select="count(child)" data-type="number" order="descending"/>
  <tr>
    <td><b><xsl:value-of select="@name" /></b></td>
    <td><xsl:value-of select="count(child)" /></td>
  </tr>
</xsl:for-each>

Редактировать: просто как дополнительная информация, вы используете фигурные скобки только для литерала, результатэлементы. Из спецификации XSLT2.0 в шаблонах значений атрибутов :

В следующем примере создается элемент результата img из элемента фотографии в источнике;значения атрибутов src и width вычисляются с использованием выражений XPath, заключенных в шаблоны значений атрибутов:

<xsl:variable name="image-dir" select="'/images'"/>
<xsl:template match="photograph">
  <img src="{$image-dir}/{href}" width="{size/@width}"/>
</xsl:template>
0 голосов
/ 20 ноября 2011

Это было какое-то время, поэтому я, возможно, запомнил это, но я считаю, что count (child) должен быть count (child :: node ()).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...