Большинство ответов связаны с изменением вызова на json.dumps (), что не всегда возможно или желательно (это может произойти, например, в компоненте framework).
Если вы хотите быть в состоянии для вызова json.dumps (obj) как есть, тогда простое решение наследуется от dict:
class FileItem(dict):
def __init__(self, fname):
dict.__init__(self, fname=fname)
f = FileItem('tasks.txt')
json.dumps(f) #No need to change anything here
Это работает, если ваш класс является просто базовым представлением данных, потому что для более сложных вещей вы всегда можете задавать ключи явно .
Я придумал это:
<(?!\/?p(?=>|\s.*>))\/?.*?>
x/
< # Match open angle bracket
(?! # Negative lookahead (Not matching and not consuming)
\/? # 0 or 1 /
p # p
(?= # Positive lookahead (Matching and not consuming)
> # > - No attributes
| # or
\s # whitespace
.* # anything up to
> # close angle brackets - with attributes
) # close positive lookahead
) # close negative lookahead
# if we have got this far then we don't match
# a p tag or closing p tag
# with or without attributes
\/? # optional close tag symbol (/)
.*? # and anything up to
> # first closing tag
/
Это будет теперь иметь дело с тегами p с или без атрибутов и закрытия p теги, но будет соответствовать пред и подобные теги, с или без атрибутов.
Это не разделяет атрибуты, но мои исходные данные не вставляет их. Я могу изменить это позже, чтобы сделать это, но это будет достаточно на данный момент.
Не уверенный, почему Вы желаете сделать, это - regex для санитизации HTML является не всегда лучшим методом (необходимо не забыть санировать атрибуты и такой, удалять JavaScript: hrefs и подобные)..., но, regex для соответствия HTML-тэгам, которые не являются <p></p>
:
(<[^pP].*?>|</[^pP]>)
Подробный:
(
< # < opening tag
[^pP].*? # p non-p character, then non-greedy anything
> # > closing tag
| # ....or....
</ # </
[^pP] # a non-p tag
> # >
)
Если Вы настоите на использовании regex, то что-то вроде этого будет работать в большинстве случаев:
# Remove all HTML except "p" tags
$html =~ s{<(?>/?)(?:[^pP]|[pP][^\s>/])[^>]*>}{}g;
Объяснение:
s{
< # opening angled bracket
(?>/?) # ratchet past optional /
(?:
[^pP] # non-p tag
| # ...or...
[pP][^\s>/] # longer tag that begins with p (e.g., <pre>)
)
[^>]* # everything until closing angled bracket
> # closing angled bracket
}{}gx; # replace with nothing, globally
, Но действительно, сохраните себя некоторые головные боли и используйте синтаксический анализатор вместо этого. CPAN имеет несколько модулей, которые подходят. Вот пример с помощью HTML:: модуль TokeParser , который идет с чрезвычайно способным HTML:: Синтаксический анализатор распределение CPAN:
use strict;
use HTML::TokeParser;
my $parser = HTML::TokeParser->new('/some/file.html')
or die "Could not open /some/file.html - $!";
while(my $t = $parser->get_token)
{
# Skip start or end tags that are not "p" tags
next if(($t->[0] eq 'S' || $t->[0] eq 'E') && lc $t->[1] ne 'p');
# Print everything else normally (see HTML::TokeParser docs for explanation)
if($t->[0] eq 'T')
{
print $t->[1];
}
else
{
print $t->[-1];
}
}
HTML:: Синтаксический анализатор принимает вход в форме имени файла, открытого дескриптора файла или строки. Обертывание вышеупомянутого кода в библиотеке и создание настраивающегося места назначения (т.е. не всего print
луг как в вышеупомянутом) не трудны. Результат будет намного более надежным, удобным в сопровождении, и возможно также быстрее (HTML:: Синтаксический анализатор использует бэкенд на базе С), чем попытка использовать регулярные выражения.
По-моему, попытка проанализировать HTML с чем-либо кроме синтаксического анализатора HTML просто просит мир боли. HTML действительно сложный язык (который является одной из основных причин, что XHTML был создан, который намного более прост, чем HTML).
, Например, это:
<HTML /
<HEAD /
<TITLE / > /
<P / >
полный, 100%-й правильно построенный, 100%-й действительный документ HTML. (Ну, это пропускает объявление DOCTYPE, но кроме этого...)
Это семантически эквивалентно
<html>
<head>
<title>
>
</title>
</head>
<body>
<p>
>
</p>
</body>
</html>
, Но это - тем не менее, допустимый HTML, с которым Вы оказываетесь перед необходимостью иметь дело. Вы могли , конечно, создайте regex для парсинга его, но, как другие, уже предложенные, с помощью фактического синтаксического анализатора HTML, просто sooo намного легче.
Предположение, что это будет работать в Perl, как он делает на языках, которые утверждают, что использовали СОВМЕСТИМЫЙ С PERL синтаксис:
/<\/?[^p][^>]*>/
РЕДАКТИРОВАНИЕ:
, Но это не будет соответствовать <pre>
или <param>
тег, к сожалению.
Это, возможно?
/<\/?(?!p>|p )[^>]+>/
, Который должен покрыть <p>
теги, которые имеют атрибуты, также.
Вы также могли бы хотеть допускать пробел перед "p" в теге p. Не уверенный, как часто Вы столкнетесь с этим, но < p> является совершенно допустимым HTML.
, Так как HTML не является регулярным языком
, HTML не является всего лишь HTML-тэгами, и они могут быть adequatly, описанным регулярными выражениями.
Так как HTML не является регулярным языком, я не ожидал бы, что регулярное выражение сделает очень хорошее задание при соответствии ему. Они могли бы быть до этой задачи (хотя я не убежден), но я рассмотрел бы взгляд в другом месте; я уверен, что жемчуг должен иметь некоторые стандартные библиотеки для управления HTML.
Так или иначе, я думал бы, что то, чему Вы хотите соответствовать, является </? (p. + |.*) (\s*.*)> нежадно (я не знаю капризы regexp синтаксиса perl, таким образом, я не могу помочь далее). Я принимаю это, \s означает пробел. Возможно, это не делает. Так или иначе Вы хотите что-то, что это будет соответствовать смещению атрибутов с имени тега пробелом. Но это более трудно, чем это, поскольку люди часто помещают незавершенные угловые скобки в сценариях и комментариях и возможно даже заключенных в кавычки значениях атрибута, против которых Вы не хотите соответствовать.
Поэтому, как я говорю, я действительно не думаю, что regexps являются правильным инструментом для задания.
Попробуйте это, это должно работать:
/<\/?([^p](\s.+?)?|..+?)>/
Объяснение: это соответствует или одной букве кроме “p”, сопровождаемого дополнительным пробелом и большим количеством символов, или нескольким буквам (по крайней мере два).
РЕДАКТИРОВАНИЕ/: я добавил способность обработать атрибуты в p
теги.
Исходный regex может быть сделан работать с очень небольшим усилием:
<(?>/?)(?!p).+?>
проблема состояла в том что/? (или \?) бросил то, чему это соответствовало, когда утверждение после того, как это перестало работать. Используя группу неотслеживания в обратном порядке (?>...) вокруг этого заботится, что это никогда не выпускает подобранную наклонную черту, таким образом, (?! p) утверждение всегда привязывается на запуске текста тега.
(Который сказал, что я соглашаюсь, что обычно парсинг HTML с regexes не является способом пойти).
Необходимо, вероятно, также удалить любые атрибуты на < тег p>, так как кто-то плохо мог сделать что-то как:
<p onclick="document.location.href='http://www.evil.com'">Clickable text</p>
самый легкий способ сделать это, должен использовать regex людей, предлагают здесь искать & ltp> теги с атрибутами, и заменяют их < p> теги без атрибутов. Только быть на безопасной стороне.
Я использовал Xetius regex и он отлично работает. За исключением некоторых flex-генерируемых тегов, которые могут быть :
без пробелов внутри. Я попытался исправить это простым ? после \s и похоже, что это работает :
<(?!\/?p(?=>|\s?.*>))\/?.*?>
Я использую его для очистки тегов из сгенерированного flex'ом html текста, поэтому я также добавил больше исключенных тегов :
<(?!\/?(p|a|b|i|u|br)(?=>|\s?.*>))\/?.*?>