计算xslt中父标记后面的标记数量

时间:2012-11-18 00:55:30

标签: xml xslt

我必须编写一个XSLT文档,该文档可以与任何XML文档一起使用,并在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。请问这个问题的任何解决方案吗?

3 个答案:

答案 0 :(得分:1)

<强>予。假设

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

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

    0.2。 film个元素都具有相同数量的同名列,您只需要:

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

    这会生成XML文档顶部元素的第一个子元素的子元素数

    3
    

    <强> II。另一种可能性:不同的film元素具有不同数量的子元素,其中一个元素具有确定表格的总列数的所有子元素

    <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文档的top元素的子元素所具有的子元素的最大数量:

    5
    

    <强> III。最后,如果film元素中没有一个元素包含列的所有元素,那么使用(ABach已经提出的内容):

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

答案 1 :(得分:0)

<强>予。 XSLT 1.0 / XPath 1.0

我不相信有一种方法可以用纯XPath 1.0来做到这一点(因为你正在寻找不同的元素名称,我认为,不是以任何特定的顺序[无论如何,我不喜欢依靠某种秩序])。

也就是说,您可以使用基于密钥的XSLT 1.0解决方案来解决问题。

当这个XSLT 1.0文档:

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

...适用于您的示例XML(包含在根元素中):

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

...生成了想要的结果:

3

如果我们对略微修改的XML应用相同的样式表:

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

...再次,产生了正确的答案:

5

注意:如果您没有显示完整的文档,我使用//表达式弥补了缺乏知识的情况。然而,这可能是在非常大的树根附近进行的昂贵操作;你会做得更好,使你的更具体。


<强> II。 XSLT 2.0 / XPath 2.0

通过使用distinct-values表达式,可以使用纯XPath 2.0获取正确的答案:

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

XSLT验证:

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

<强>结果:

3

答案 2 :(得分: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>