Как использовать регулярные выражения для поиска значений атрибутов в кавычках в файле OPML (XML)

Я ищу в файле OPML, который выглядит примерно так. Я хочу вытащить наброски текста и xmlUrl.

  <outline text="lol">
  <outline text="Discourse on the Otter" xmlUrl="http://discourseontheotter.tumblr.com/rss" htmlUrl="http://discourseontheotter.tumblr.com/"/>
  <outline text="fedoras of okc" xmlUrl="http://fedorasofokc.tumblr.com/rss" htmlUrl="http://fedorasofokc.tumblr.com/"/>
  </outline>

Моя функция:

 import re
 rssName = 'outline text="(.*?)"'
 rssUrl =  'xmlUrl="(.*?)"'

 def rssSearch():
     doc = open('ttrss.txt')
     for line in doc:
        if "xmlUrl" in line:
            mName = re.search(rssName, line)
            mUrl = re.search(rssUrl, line)
            if mName is not None:
                print mName.group()
                print mUrl.group()

Однако возвращаемые значения выглядят так:

 outline text="fedoras of okc"
 xmlUrl="http://fedorasofokc.tumblr.com/rss"

Каково правильное выражение регулярного выражения для rssName и rssUrl, чтобы я возвращал только строку между кавычками?

2 ответа

Решение

Не используйте регулярные выражения для разбора XML. Код грязный, и слишком много вещей может пойти не так.

Например, что если ваш провайдер OPML переформатирует свой вывод следующим образом:

<outline text="lol">
  <outline
      htmlUrl="http://discourseontheotter.tumblr.com/"
      xmlUrl="http://discourseontheotter.tumblr.com/rss"
      text="Discourse on the Otter"
  />
  <outline
      htmlUrl="http://fedorasofokc.tumblr.com/"
      xmlUrl="http://fedorasofokc.tumblr.com/rss"
      text="fedoras of okc"
  />
</outline>

Это совершенно верно, и это означает то же самое. Но линейно-ориентированный поиск и регулярные выражения, такие как 'outline text="(.*?)"' сломает.

Вместо этого используйте синтаксический анализатор XML. Ваш код будет чище, проще и надежнее:

import xml.etree.cElementTree as ET

root = ET.parse('ttrss.txt').getroot()
for outline in root.iter('outline'):
    text = outline.get('text')
    xmlUrl = outline.get('xmlUrl')
    if text and xmlUrl:
        print text
        print xmlUrl

Это относится и к вашему фрагменту OPML, и к аналогичным файлам OPML, которые я нашел в Интернете, например, к списку политологов. И это очень просто, ничего сложного в этом нет. (Я не хвастаюсь, это просто преимущество, которое вы получаете от использования парсера XML вместо регулярных выражений.)

Пытаться

print mName.group(1)
print mUrl.group(1)

http://docs.python.org/2/library/re.html

Если аргумент groupN равен нулю, соответствующим возвращаемым значением является вся совпадающая строка; если он находится в включающем диапазоне [1..99], это строка, соответствующая соответствующей группе в скобках.

или же

rssName = 'outline text="(?P<text>.*?)"'

а потом

print mName.group('text')
Другие вопросы по тегам