Как я могу проверить, содержит ли HTML расширенные объекты, такие как <? - PullRequest
2 голосов
/ 20 октября 2010

Допустим, у нас есть HTML-строка типа "2 &lt; 4"

Как определить, содержит ли он какие-либо из этих расширенных последовательностей?

Я нашел HTML :: Entities в CPAN, но он не предоставляет метод 'check'.

Подробности: исправление метода 'truncate', чтобы не оставлять поврежденную строку типа "2 &l" и не выполнять ненужную работу Это должно выглядеть так

$s = HTML::Entities::decode_entities ($s) if $has_ext_chars;
$s = substr ($s, 0, $len - 3) . '...' if length $s > $len;
$s = HTML::Entities::encode_entities ($s, "‚„-‰‹‘-™›\xA0¤¦§©«-®°-±µ-·»") if $has_ext_chars;

Как определить $ has_ext_chars?

Ответы [ 4 ]

1 голос
/ 20 октября 2010

Полный список символьных сущностей можно найти в справочнике W3C .

Вы также должны соответствовать \&#u?\d+; и \&#x[a-fA-F0-9]+;

1 голос
/ 20 октября 2010

Из perldoc HTML :: Entities :

Модуль также может экспортировать хэши% char2entity и% entity2char, которые содержат сопоставление всех символов в соответствующие сущности(и наоборот, соответственно).

Вы, вероятно, можете использовать их для построения регулярных выражений.Например, для сопоставления сущностей:

use HTML::Entities '%entity2char';

my $regex = "&(?:" . join("|", map {s/;\z//; $_} keys %entity2char) . ");";

if ($str =~ /$regex/) {
    print "$str contains entities\n";
}

Это будет пропускать сущности, подобные &#entity_number;.

0 голосов
/ 20 октября 2010

Из вашего примера кода вы, вероятно, только что внедрили атаку межсайтового скриптинга в свое приложение.Если бы я заставил ваш код обрабатывать что-то вроде &lt;script src="evil.example.com"&gt;&lt;/script&gt;, ваш код декодировал бы его в действительный HTML, а не перекодировал бы < и > обратно в сущности.(Угловые скобки в коде не являются угловыми скобками ASCII.)

Если вы усекаете строку, содержащую какие-либо HTML-теги или объекты, вы, вероятно, что-то сломаете, если будете использовать простое решение.Возможно, вам лучше создать решение, основанное на модуле парсинга HTML.Если вы смотрите только на текст внутри элемента, в котором нет элементов, вы можете захватить текст, обрезать его и затем вернуть обратно в элемент.Если вам придется иметь дело со смешанным контентом, это будет сложнее.

Но в интересах плохих решений:

#treats each entity as one character "2 &lt; 4" is 5 characters long
$trunc_len = $len - 3;
$str =~ s/^((?>(?:[^&]|&[^\s;]+;?){$trunc_len}))(?:[^&]|&[^\s;]+;?){4,}/$1.../;

#abuses proceadural nature of the regexp engine 
#treats each input character as on character "2 &lt; 4" is 8 characters long
$str =~ s/^( (?:[^&]|&[^\s;]+;?)+ )(?(?{ $found = (pos() > ( $found ? $len - 3 : $len ))})(?!)).*$(?(?{pos() < $len })(?!))/$1.../x;

И то, и другое является довольно допустимым в том, что является сущностью, допускающей общие странные особенности браузера.

0 голосов
/ 20 октября 2010

Вы можете попробовать это с регулярным выражением

$str =~ /.*\&[^\s]+;.*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...