Проблема значительно усложняется тем фактом, что тег <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>