2

我必须编写一个可与​​任何 XML 文档一起使用的 XSLT 文档,并将结果显示在 HTML 表中。表格的列都取决于 XML 文档中有多少标签。我试图使用

<xsl:value-of select="count(/*/*/)"/> 

计算标签的数量。

但我想要,例如,如果我有:

  <film>
      <title></title>
      <year></year>
      <actor></actor>
  </film>
  <film>
      <title></title>
      <year></year>
      <actor></actor>
  </film>

结果将是 3 而不是当前显示的 6。请问这个问题有什么解决办法吗?

4

3 回答 3

1

一、假设

  1. 您有一个格式良好的 XML 文档,例如:

. . . .

<films>
  <film>
    <title/>
    <year/>
    <actor/>
  </film>
  <film>
    <title/>
    <year/>
    <actor/>
  </film>
</films>

.2. 元素都具有相同数量的film同名列,那么您只需要:

 count(/*/*[1]/*)

这将产生 XML 文档顶部元素的第一个子元素的子元素的数量

3

二、另一种可能性:不同film的元素有不同数量的子元素,其中一个元素的所有子元素决定了 table 的总列数

<films>
  <film>
    <title/>
    <year/>
    <actor/>
  </film>
  <film>
    <title/>
    <year/>
    <actor/>
    <rating/>
    <director/>
  </film>
  <film>
    <title/>
    <year/>
    <actor/>
    <rating/>
  </film>
</films>

然后,使用 XPath 2.0,使用:

max(/*/*/count(*))

这将产生 XML 文档顶部元素的子元素具有的最大子元素数:

5

三、最后,如果没有一个film元素可能包含列的所有元素,则使用(ABach 已经提出的):

count(distinct-values(/*/*/*/name()))
于 2012-11-18T03:37:40.673 回答
0

I. XSLT 1.0/XPath 1.0

I don't believe there is a way to do this with pure XPath 1.0 (since you are looking for distinct element names that are, I assume, not in any particular order [at any rate, I don't like to rely on there being some sort of order]).

That said, you can use a key-based XSLT 1.0 solution to solve the problem.

When this XSLT 1.0 document:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kFilmChildren" match="film/*" use="name()"/>

  <xsl:template match="/">
    <xsl:value-of
      select="count(//film/*[
                generate-id() = 
                generate-id(key('kFilmChildren', name())[1])
      ])"/>
  </xsl:template>
</xsl:stylesheet>

...is applied against your sample XML (wrapped in a root element):

<films>
  <film>
    <title/>
    <year/>
    <actor/>
  </film>
  <film>
    <title/>
    <year/>
    <actor/>
  </film>
</films>

...the wanted result is produced:

3

If we apply the same stylesheet against a slightly modified XML:

<films>
  <film>
    <title/>
    <year/>
    <actor/>
    <test/>
  </film>
  <film>
    <title/>
    <year/>
    <actor/>
    <test/>
    <test2/>
  </film>
</films>

...again, the correct answer is produced:

5

NOTE: given that you did not show a complete document, I made up for that lacking knowledge by using the // expression. That, however, can be an expensive operation near the root of very large trees; you would do well to make yours more specific.


II. XSLT 2.0/XPath 2.0

Pure XPath 2.0 can be used to obtain the correct answer by utlizing the distinct-values expression:

count(distinct-values(//film/*/name()))

XSLT Verification:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output omit-xml-declaration="no" indent="yes" method="text" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/">
     <xsl:value-of select="count(distinct-values(//film/*/name()))" />
  </xsl:template>

</xsl:stylesheet>

Result:

3
于 2012-11-18T02:19:54.563 回答
0

您的文档实际上包含 16 个标签:8 个开始标签和 8 个结束标签。所以我怀疑“计算标签”不是你真正的要求。由于您的术语不正确,我们只能猜测您的真实需求。我怀疑它可能是制作一个表格,每个不同的元素名称都有一行,其中包含具有该名称的元素数量的计数。这将是:

<table>
  <xsl:for-each-group select="//*" group-by="name()">
    <tr>
      <td><xsl:value-of select="current-grouping-key()"/></td>
      <td><xsl:value-of select="count(current-group()"/></td>
    </tr>
  </xsl:for-each-group>
</table>
于 2012-11-18T08:34:47.150 回答