Какой элемент HTML имеет наибольшее количество дочерних элементов определенного типа, например теги? - PullRequest
1 голос
/ 20 февраля 2009

На любом языке, XSLT , PHP, Ruby, Perl, что угодно: как я могу получить XPath или другой путь или идентификатор для элемента, содержащего наибольшее количество тегов <p>?

Ответы [ 5 ]

4 голосов
/ 20 февраля 2009

Этот ответ предполагает, что ввод 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 children :

<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))]
0 голосов
/ 21 мая 2010

После попытки построить это рекурсивный дизайн ... Я увидел простое решение 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>

0 голосов
/ 20 февраля 2009

Ответ зависит от языка. JavaScript, например, может естественно обрабатывать просмотр HTML DOM, и есть библиотеки, такие как ProtoType, которые быстро справятся с этим. Точно так же ответ Гаранна поможет вам в этом.

На других языках я бы предложил использовать регулярные выражения для поиска тегов, в которых есть теги абзаца. Скорее всего, это повлечет за собой превращение всего HTML-кода в одну строку и его обработку.

Предполагая, что это правильно отформатированный HTML, вы можете удалить весь контент, оставив только теги. Выполнение этого сначала сделает последующие шаги более быстрыми. Тогда, скорее всего, речь идет о некоторых циклах и счетчиках.

0 голосов
/ 20 февраля 2009

Очень грубое решение в 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"; 
0 голосов
/ 20 февраля 2009

Вы можете использовать getElementsByTagName, чтобы найти свои

s и перебрать результаты, чтобы найти наибольшее значение childNodes.length с Javascript (при условии, что у вас есть возможность сделать это на стороне клиента).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...