Регулярное выражение для соответствия каждому символу новой строки (\n) внутри тега <content>

Я ищу регулярное выражение, чтобы соответствовать каждому символу новой строки (\n) внутри тега XML, который <content>или внутри любого тега, который находится внутри этого <content> тег, например:

<blog>
<text>
(Do NOT match new lines here)
</text>
<content>
(DO match new lines here)
<p>
(Do match new lines here)
</p>
</content>
(Do NOT match new lines here)
<content>
(DO match new lines here)
</content>

2 ответа

Решение

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

<!-- <content> blah </content> -->

Вы можете использовать два подхода здесь:

  1. Сначала удалите все комментарии. Затем используйте подход регулярных выражений.
  2. Не используйте регулярные выражения и используйте контекстно-зависимый подход к анализу, который может отслеживать, вложены ли вы в комментарии или нет.

Быть осторожен.

Я также не уверен, что вы можете сопоставить все новые строки сразу. @Quartz предложил это:

<content>([^\n]*\n+)+</content>

Это будет соответствовать любым тегам содержимого, которые имеют символ новой строки ПРАВО ПЕРЕД закрывающим тегом... но я не уверен, что вы подразумеваете под соответствием всем символам новой строки. Хотите ли вы иметь доступ ко всем соответствующим символам новой строки? Если это так, то лучше всего захватить все теги содержимого, а затем найти все символы перевода строки, расположенные между ними. Нечто подобное:

<content>.*</content>

НО ЕСТЬ ОДНА ПРОБЛЕМА: регулярные выражения являются жадными, поэтому это регулярное выражение будет сопоставлять первый открывающий тег с последним закрывающим. Вместо этого вы должны подавить регулярное выражение, чтобы оно не было жадным. В таких языках, как python, вы можете сделать это с помощью "?" символ регулярного выражения

Я надеюсь, что с этим вы сможете увидеть некоторые подводные камни и выяснить, как вы хотите действовать. Вероятно, вам лучше использовать библиотеку синтаксического анализа XML, а затем перебирать все теги содержимого.

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

ОБНОВЛЕНИЕ 1:

Позвольте мне подвести итог немного подробнее и добавить некоторые подробности в мой ответ. Я собираюсь использовать синтаксис регулярных выражений в Python, потому что это то, к чему я больше привык (простите меня заранее... возможно, вам придется экранировать некоторые символы... прокомментируйте мой пост, и я исправлю его):

Чтобы удалить комментарии, используйте это регулярное выражение: обратите внимание на "?" подавляет.*, чтобы сделать его не жадным.

Аналогично, для поиска тегов содержимого используйте: .*?

Кроме того, вы можете попробовать это и получить доступ к каждому символу новой строки с помощью групп объектов соответствия ():

<content>(.*?(\n))+.*?</content>

Я знаю, что мое побег выключен, но это отражает идею. Этот последний пример, вероятно, не сработает, но я думаю, что лучше всего выразить то, что вы хотите. Мое предложение остается: либо возьмите все теги содержимого и сделайте это самостоятельно, либо используйте библиотеку синтаксического анализа.

ОБНОВЛЕНИЕ 2:

Так вот код Python, который должен работать. Я до сих пор не уверен, что вы подразумеваете под "найти" все новые строки. Вы хотите целые строки? Или просто посчитать, сколько новых строк. Чтобы получить реальные строки, попробуйте:

#!/usr/bin/python

import re

def FindContentNewlines(xml_text):
    # May want to compile these regexes elsewhere, but I do it here for brevity
    comments = re.compile(r"<!--.*?-->", re.DOTALL)
    content = re.compile(r"<content>(.*?)</content>", re.DOTALL)
    newlines = re.compile(r"^(.*?)$", re.MULTILINE|re.DOTALL)

    # strip comments: this actually may not be reliable for "nested comments"
    # How does xml handle <!--  <!-- --> -->. I am not sure. But that COULD
    # be trouble.
    xml_text = re.sub(comments, "", xml_text)

    result = []
    all_contents = re.findall(content, xml_text)
    for c in all_contents:
        result.extend(re.findall(newlines, c))

    return result

if __name__ == "__main__":
    example = """

<!-- This stuff
ought to be omitted
<content>
  omitted
</content>
-->

This stuff is good
<content>
<p>
  haha!
</p>
</content>

This is not found
"""
    print FindContentNewlines(example)

Эта программа печатает результат:

 ['', '<p>', '  haha!', '</p>', '']

Первая и последняя пустые строки происходят от символов новой строки, непосредственно предшествующих первой <p> и тот, который идет сразу после </p>, В целом это (по большей части) делает свое дело. Поэкспериментируйте с этим кодом и уточните его для своих нужд. Распечатайте материал посередине, чтобы вы могли видеть, какие регулярные выражения совпадают и не совпадают.

Надеюсь это поможет:-).

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

<content>(?:[^\n]*(\n+))+</content>
Другие вопросы по тегам