【问题标题】:Which HTML element has the largest number of children of a certain type, for instance tags?哪个 HTML 元素具有最多的某种类型的子元素,例如标签?
【发布时间】:2009-02-20 16:12:51
【问题描述】:

在任何语言中,XSLT、PHP、Ruby、Perl 等任何语言:如何获取包含最多 <p> 标记的元素的 XPath 或其他路径或标识符?

【问题讨论】:

  • Stuart,你知道为什么这个问题会被放到社区 wiki 中吗?这不是一件好事,也许可以解释为什么没有这么多答案。
  • 我勾选了这个框。我想敞开心扉。为什么这是一件坏事?
  • 因为问题和答案的投票不影响作者的声誉。最好联系 team@stackoverflow.com,向他们解释问题并要求他们将问题和答案恢复为非社区 wiki 状态。谢谢。
  • 因此,例如在这种情况下,每次有人投票支持您的问题时,您不会获得应得的 10 分——这些是关于“社区 wiki”的规则.

标签: html language-agnostic xslt xpath


【解决方案1】:

此答案假设 html 输入是格式良好的 XML 文档(例如 XHtml 文档)。

在 XSLT 1.0 中:

给定以下 XML

<html>
    <div id='A1'>
        <p/>
        <p/>
    </div>
    <div id='A2'>
        <p/>
        <p/>
        <p/>
        <p/>
    </div>
    <div id='A3'>
        <p/>
        <p/>
        <p/>
    </div>
</html>

这种转换产生pchildren 数量最多的元素

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:key name="kElByP" match="*" use="boolean(p)"/>

    <xsl:template match="/*">
      <xsl:for-each select="key('kElByP', 'true')">
        <xsl:sort data-type="number" order="descending"
         select="count(p)"/>

         <xsl:if test="position() = 1">
           <xsl:copy-of select="."/>
         </xsl:if>
      </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

当对 XML 文档应用上述转换时,会产生正确的结果

<div id="A2">
        <p />
        <p />
        <p />
        <p />
    </div>

使用 XPath 2.0:

//*[count(p) = max(//*/count(p))]

【讨论】:

  • 我一直在思考 XPath 1.0 解决方案,但我不相信存在这样的解决方案。你说什么?
  • 我想如果不是 xhtml 我可以先整理一下
  • @Tomalak 不,除非 XPath 托管在 XSLT 中,但即使在这种情况下,它也会很棘手,并且在 XSLT 中寻找效率低于 xslt 代码的 XPath 单行代码是没有意义的.主要原因是最大值在计算值上。如果最大值在 elem/attr 上,则存在 1 行
  • @Tomalak 为什么最近我回答的大多数问题都放在社区 wiki 中?让我有很多时间来找出为什么我的代表没有反映新的投票。非常糟糕:(
  • @Dimitre:维基模式是强制继承自问题的,任何帖子在第七次编辑后都会变成维基。我想那是因为人们在发帖前应该三思而后行,不要经常更改它,否则代表对该帖子毫无意义。
【解决方案2】:

您可以使用 getElementsByTagName 找到您的

s 并循环遍历结果以使用 Javascript 找到 childNodes.length 的最大值(假设您可以选择在客户端执行此操作)。

【讨论】:

    【解决方案3】:

    答案取决于语言。例如,JavaScript 可以自然地处理查看 HTML DOM,并且有诸如 ProtoType 之类的库可以快速处理它。同样,Garann 的回答会让您顺利上路。

    在其他语言中,我建议使用正则表达式来查找其中包含段落标签的标签。这可能涉及将整个 html 转换为单个字符串并对其进行处理。

    假设它是格式正确的 HTML,您可以删除所有内容,只留下标签。首先这样做会使后续步骤更快。那么这可能是一些循环和一些计数器的问题。

    【讨论】:

    • 拒绝正则表达式,DOM 结构不规则
    【解决方案4】:

    Perl 中非常暴力的解决方案,使用 XML::Twig:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    use XML::Twig;
    
    my $max=0; # max number of p's
    my $path;  # path to the element
    
    XML::Twig->new( twig_handlers => 
                      { # _all_ is called for every single element in the XML
                        _all_ => sub { # $_ is the element
                                       my $nb_p= $_->children( 'p'); 
                                       if( $nb_p > $max)
                                         { $max= $nb_p; 
                                           $path= $_->xpath;
                                         }
                                     }
                      },
                  )
             ->parsefile( $ARGV[0]);
    print "$path  ($max p)\n"; 
    

    【讨论】:

      【解决方案5】:

      在尝试构建这是一个递归设计之后...我看到了简单的 2.0 解决方案。那好吧。无论如何,另一种解决方案。

      <xsl:template match="/">
          <xsl:variable name="MaxElements">
                  <xsl:call-template name="MaxElements">
                      <xsl:with-param name="elements" select="//div[p]"/>
                      <xsl:with-param name="largestSoFar" select="0"/>
                  </xsl:call-template>
          </xsl:variable>
          <xsl:value-of select="$MaxElements"/>
      </xsl:template>
      <xsl:template name="MaxElements">
          <xsl:param name="elements"/>
          <xsl:param name="largestSoFar"/>
          <xsl:choose>
              <xsl:when test="$elements">
                  <xsl:variable name="CurrentNumber" select="count($elements[1]/p)"/>
                  <xsl:variable name="LargerNumber" select="if ($CurrentNumber > $largestSoFar) then ($CurrentNumber) else $largestSoFar"/>
                  <xsl:call-template name="MaxElements">
                      <xsl:with-param name="elements" select="$elements[position()>1]"/>
                      <xsl:with-param name="largestSoFar" select="$LargerNumber"/>
                  </xsl:call-template>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:value-of select="$largestSoFar"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:template>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 2014-10-10
        相关资源
        最近更新 更多