xslt 按子元素计数排序

发布于 2024-12-16 21:48:50 字数 1650 浏览 0 评论 0原文

我正在尝试通过查询 xml 文档来创建 html 表。我正在使用 xslt。

问题就在这里。 “父”节点包含许多“子”节点。我必须 o/pa 表,其中包含父级的 @name 和按排序顺序(降序)的“子”节点数。所以我正在这样做,

 <?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>

I am trying to create an html table by querying on an xml document. I am using xslt.

Here is the problem. "parent" node contains many "child" nodes. I have to o/p a table that contains @name of parent and count of "child" nodes in sorted order(descending). So I am doing

 <?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) > 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>

I get the html however the only problem is I am not getting it in sorted order by count of child elements. I suspect I am using count incorrectly xsl:sort? Can you help?

Input 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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡淡的优雅 2024-12-23 21:48:50

提供的XSLT代码中有很多错误!

最大的问题在这里:

 
      
      
        
        
      
    

这不会执行任何有意义的排序,因为要排序的节点的节点集仅包含一个节点——当前节点。

下一个问题在这里

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

XSLT 指令的任何 select 属性中不应该有任何 AVT - 您需要删除花括号。

第三个问题是排序指定得太晚 - 在模板 mathcing parent 内。 父级没有任何自己有 child< 的子级。 /code> 孩子们。

解决方案:纠正上面讨论的所有主要问题,可能会得到以下代码:

<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>

There are numerous mistakes in the provided XSLT code!

The biggest problem is here:

    <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>

This will not perform any meaningful sort, because the node-set of the nodes to be sorted contains only one node -- the current node.

The next problem is here:

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

There shouldn't be any AVT in any select attribute of an XSLT instruction -- you need to remove the curly braces.

The 3rd problem is that the sort is specified too-late -- inside the template mathcing parent. A parent doesn't have any children that themselves have child children.

Solution: Correcting all major problems, discussed above, one may arrive at the following code:

<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>

when this transformation is applied on the provided XML document:

<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>

the wanted-sorted result is produced:

<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>
若言繁花未落 2024-12-23 21:48:50

几乎。您不需要将 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 表达式计算
模板:

/>

  

Almost. You don't need the curly braces around your xsl:sort select="..."
Your for-each would then look like:

<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>

Edit: Just as an added bit of information, you only use curly braces on literal, result elements. From the XSLT2.0 spec on attribute value templates:

The following example creates an img result element from a photograph
element in the source; the value of the src and width attributes are
computed using XPath expressions enclosed in attribute value
templates:

<xsl:variable name="image-dir" select="'/images'"/>
<xsl:template match="photograph">
  <img src="{$image-dir}/{href}" width="{size/@width}"/>
</xsl:template>
嗼ふ静 2024-12-23 21:48:50

已经有一段时间了,所以我可能记错了,但我相信 count(child) 应该是 count(child::node()) 。

It's been a while, so I may be misremembering this, but I believe that count(child) should be count(child::node()).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文