Регулярное выражение для соответствия каждому символу новой строки (\ n) внутри тега <content> - PullRequest
52 голосов
/ 13 июля 2009

Я ищу регулярное выражение для соответствия каждому символу новой строки (\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 ]

71 голосов
/ 13 июля 2009

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

<!-- <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 - мне не особо повезло, попробовав свое регулярное выражение из моего первого обновления, чтобы захватить все новые строки ... дайте мне знать, если вы это сделаете.

4 голосов
/ 13 июля 2009
<content>(?:[^\n]*(\n+))+</content>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...