Python регулярное выражение

1

Я пытаюсь извлечь ВСЕ разрешения экрана телефона из XML файла WURFL с помощью ниже Python script. Проблема в том, что я получаю только первый матч. Зачем? Как я могу получить все совпадения?

XML файл WURFL можно найти по адресу http://sourceforge.net/projects/wurfl/files/WURFL/latest/wurfl-latest.zip/download?use_mirror=freefr

def read_file(file_name):
    f = open(file_name, 'rb')
    data = f.read()
    f.close()
    return data

text = read_file('wurfl.xml')

import re
pattern = '<device id="(.*?)".*actual_device_root="true">.*<capability name="resolution_width" value="(\d+)"/>.*<capability name="resolution_height" value="(\d+)"/>.*</device>'
for m in re.findall(pattern, text, re.DOTALL):
    print(m)
Теги:
wurfl

4 ответа

1

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

Во-вторых, если вы настаиваете на использовании регулярных выражений, используйте finditer() вместо findall().

В-третьих, ваше регулярное выражение совпадает с первой записью до последней (.* является жадным, и вы установили режим DOTALL), поэтому либо увидите первый абзац, либо, по крайней мере, измените ваше регулярное выражение на

pattern = r'<device id="(.*?)".*?actual_device_root="true">.*?<capability name="resolution_width" value="(\d+)"/>.*?<capability name="resolution_height" value="(\d+)"/>.*?</device>'

Также всегда используйте необработанные строки с регулярными выражениями. \d срабатывает, \b будет вести себя неожиданно в "нормальной" строке.

  • 0
    Спасибо за ваш вклад, но я все еще получаю только один матч
  • 0
    К сожалению, я пропустил один жадный квантификатор. Пожалуйста, попробуйте снова с отредактированным регулярным выражением.
0

Я, конечно, не прочь обращаться с xml с регулярным выражением, если требования просты, но, возможно, в этом случае использование реального анализатора XML будет лучше. Используя модуль stdlib etree и разбрызгивание (imho) отвратительных xpaths:

import xml.etree.ElementTree as ET

def capability_value(cap_elem):
    if cap_elem is None:
        return None
    return int(cap_elem.attrib.get('value'))

def devices(wurfl_doc):
    for el in wurfl_doc.findall("/devices/device[@actual_device_root='true']"):
        width = el.find("./group[@id='display']/capability[@name='resolution_width']")
        width = capability_value(width)
        height = el.find("./group[@id='display']/capability[@name='resolution_height']")
        height = capability_value(height)
        device = {
            'id' : el.attrib.get('id'), 
            'resolution' : {'width': width, 'height': height}
        }
        yield device

doc = ET.ElementTree(file='wurfl.xml')
for device in devices(doc):
    print device
0

Вы используете "жадные" совпадения: .* будет соответствовать количеству текста, которое он может захватить, что означает, что .* до <capabilities> соответствует большей части файла.

text = open('wurfl.xml').read()
pattern = r'<device id="(.*?)".*?actual_device_root="true">.*?<capability name="resolution_width" value="(\d+)"/>.*?<capability name="resolution_height" value="(\d+)"/>.*?</device>'
for m in re.findall(pattern, text, re.DOTALL):
    print m
0

Это нечетность в поведении findall, в частности findall возвращает только первую сопоставимую группу из каждого совпадения шаблонов. См. этот вопрос.

  • 0
    Уточнение: я получаю группы, в которых я заинтересован, но findall возвращает ОДНО совпадение (первое совпадение) по какой-то причине.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню