哪个HTML元素具有特定类型的子项数最多,例如标记?

时间:2009-02-20 16:12:52

标签: html language-agnostic xslt xpath

在任何语言中,XSLT,PHP,Ruby,Perl,任何东西:我如何获得包含最多<p>个标签的元素的XPath或其他路径或标识符?

5 个答案:

答案 0 :(得分:4)

这个答案假设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>

此转换生成的p子项数最多的元素

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

答案 1 :(得分:0)

您可以使用getElementsByTagName查找&lt; p&gt;并循环搜索结果,以使用Javascript查找childNodes.length的最大值(假设您可以选择在客户端执行此操作)。

答案 2 :(得分:0)

答案取决于语言。例如,JavaScript可以自然地处理查看HTML DOM,并且有像ProtoType这样的库可以快速处理它。同样,Garann的回答可以帮助你。

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

假设HTML格式正确,您可以删除所有内容,只留下标签。首先执行此操作会使后续步骤更快地进行。然后它可能是一些循环和一些计数器的问题。

答案 3 :(得分:0)

使用XML :: Twig:

在Perl中使用非常强力的解决方案
#!/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"; 

答案 4 :(得分:0)

尝试构建之后是一个递归设计......我看到了简单的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>