Regex для сопоставления только книги ('knjiga') с определенным именем ('naslov') - PullRequest
0 голосов
/ 24 октября 2019

У меня есть простой xml:

<?xml version="1.0" encoding="utf-8" ?>
<book_list>
    <book rbr="1" >
        <title> Yacc </title>
        <author> Filip Maric </author>
        <year> 2004 </year>
        <publisher> Matematicki fakultet </publisher>
        <price currency="din"> 100 </price>
    </book>
    <book rbr="2" >
        <author> Fredrik Lundh </author>
        <price currency="eur"> 50 </price>
        <publisher> O’Reilly & Associates </publisher>
        <year> 2001 </year>
        <title> Python Standard Library </title>
    </book>
</book_list>

Мне нужно сопоставить книгу с определенным именем с регулярным выражением в Python. Я могу легко сопоставить любую книгу с:

r'<book\s*rbr="\d+"\s*>.*?</book>'

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

r'<book\s*rbr="\d+"\s*>(?P<book>.*?<title> Python Standard Library </title>.*?)</book>'

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

Как правильно сделать это, которое подойдет для любого количества книг в book_list?

1 Ответ

0 голосов
/ 24 октября 2019

Проблема значительно усложняется тем фактом, что тег <title> не всегда является первым дочерним тегом под <book>. Если бы это было так, вы могли бы использовать:

m = re.search(r'<book\s*rbr="\d+"\s*>\s*(?P<book><title> Python Standard Library </title>).*?</book>', xml, flags=re.DOTALL)

То есть заменить .*? на \s*.

Хитрость заключается в том, чтобы убедиться, что после того, как вы сопоставили <book> отметьте, что тег <title>, который вы ищете, не следует за будущим тегом </book>. Это может быть достигнуто с отрицательным взглядом (это не красиво):

import re

xml = """<?xml version="1.0" encoding="utf-8" ?>
<book_list>
    <book rbr="1" >
        <title> Yacc </title>
        <author> Filip Maric </author>
        <year> 2004 </year>
        <publisher> Matematicki fakultet </publisher>
        <price currency="din"> 100 </price>
    </book>
    <book rbr="2" >
        <author> Fredrik Lundh </author>
        <price currency="eur"> 50 </price>
        <publisher> O’Reilly & Associates </publisher>
        <year> 2001 </year>
        <title> Python Standard Library </title>
    </book>
</book_list>"""

m = re.search(r'<book\s*rbr="\d+"\s*>(?!.*</book>.*<title> Python Standard Library </title>).*(?P<book><title> Python Standard Library </title>).*?</book>', xml, flags=re.DOTALL)
print(m.group('book'))
m = re.search(r'<book\s*rbr="\d+"\s*>(?!.*</book>.*<title> Yacc </title>).*(?P<book><title> Yacc </title>).*?</book>', xml, flags=re.DOTALL)
print(m.group('book'))

Отпечатки:

<title> Python Standard Library </title>
<title> Yacc </title>

См. Демонстрацию

Вы можетеуменьшите избыточность, используя форматированные строковые литералы , если ваш Python поддерживает их (или метод str.format, если он не поддерживает):

title = '<title> Python Standard Library </title>'
m = re.search(rf'<book\s*rbr="\d+"\s*>(?!.*</book>.*{title}).*(?P<book>{title}).*?</book>', xml, flags=re.DOTALL)

Альтернативный подход

При таком подходе создается список всех отдельных тегов <book>, а затем выполняется поиск по каждому из них в порядке поиска интересующего заголовка:

# create list of <book> ... </book> strings:
books = re.findall(r'<book\s*rbr="\d+"\s*>.*?</book>', xml, flags=re.DOTALL)
title = '<title> Python Standard Library </title>'
# now search each <book>...</book> string looking for the title string:
for book in books:
    if re.search(rf'{title}', book):
        print(title)
        print(book)

Печать:

<title> Python Standard Library </title>
<book rbr="2" >
        <author> Fredrik Lundh </author>
        <price currency="eur"> 50 </price>
        <publisher> O'Reilly & Associates </publisher>
        <year> 2001 </year>
        <title> Python Standard Library </title>
    </book>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...