XML парсинг с Python и регулярное выражение не возвращает все результаты - PullRequest
0 голосов
/ 17 февраля 2020

Я все еще борюсь с регулярным выражением:

import re

text = '''
          <SW-VARIABLE>
            <SHORT-NAME>abc</SHORT-NAME>
            <CATEGORY>VALUE</CATEGORY>
            <SW-ARRAYSIZE>
              <VF>4</VF>
            </SW-ARRAYSIZE>
            <SW-DATA-DEF-PROPS>
              cde
            </SW-DATA-DEF-PROPS>
          </SW-VARIABLE>

          <SW-VARIABLE>
            <SHORT-NAME>def</SHORT-NAME>
            <CATEGORY>VALUE</CATEGORY>
            <SW-ARRAYSIZE>
              <VF>8</VF>
            </SW-ARRAYSIZE>
            <SW-DATA-DEF-PROPS>
                <HELLO>dsfadsf </HELLO>
                <NO>itis</NO>
            </SW-DATA-DEF-PROPS>
          </SW-VARIABLE>
'''

pattern = r'<SW-VARIABLE>\s*<SHORT-NAME>([^<]*)</SHORT-NAME>.*<SW-ARRAYSIZE>\s*<VF>([^<]*)</VF>\s*</SW-ARRAYSIZE>.*?<(?:/(?!<SW-VARIABLE>)[^/]*?)SW-VARIABLE>'

print(re.findall(pattern, text, re.S))

Это возвращает:

[('abc', '8')]

Я ожидаю, что оно вернется:

[('abc', '4'), ('def', '8')]

Почему это так жадно и соответствует всему до последнего закрывающего тега?

Это ссылка на regex101: https://regex101.com/r/ANO7RA/1

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

)

Ответы [ 4 ]

2 голосов
/ 17 февраля 2020

Это шаблон, который вам нужен.

pattern = r'<SW-VARIABLE>\s*<SHORT-NAME>([^<].*?)</SHORT-NAME>.*?<SW-ARRAYSIZE>\s*<VF>([^<]*?)</VF>\s*</SW-ARRAYSIZE>.*?<(?:/(?!<SW-VARIABLE>)[^/]*?)SW-VARIABLE>'

1 голос
/ 17 февраля 2020

Вы также можете проверить это:

import re

text = '''
          <SW-VARIABLE>
            <SHORT-NAME>abc</SHORT-NAME>
            <CATEGORY>VALUE</CATEGORY>
            <SW-ARRAYSIZE>
              <VF>4</VF>
            </SW-ARRAYSIZE>
            <SW-DATA-DEF-PROPS>
              cde
            </SW-DATA-DEF-PROPS>
          </SW-VARIABLE>

          <SW-VARIABLE>
            <SHORT-NAME>def</SHORT-NAME>
            <CATEGORY>VALUE</CATEGORY>
            <SW-ARRAYSIZE>
              <VF>8</VF>
            </SW-ARRAYSIZE>
            <SW-DATA-DEF-PROPS>
                <HELLO>dsfadsf </HELLO>
                <NO>itis</NO>
            </SW-DATA-DEF-PROPS>
          </SW-VARIABLE>
'''
pattern=r'<SW-VARIABLE>\s*<SHORT-NAME>([^<].*?)</SHORT-NAME>.*?<SW-ARRAYSIZE>\s*<VF>([^<]*?)</VF>\s*</SW-ARRAYSIZE>.*?</SW-VARIABLE>'
print(re.findall(pattern, text, re.S))

вывод:

[('abc', '4'), ('def', '8')]
1 голос
/ 17 февраля 2020

Я согласен с другими, лучше использовать парсер xml здесь. Но чтобы исправить то, что у вас есть ...

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

<SW-VARIABLE>\s*<SHORT-NAME>([^<]*)</SHORT-NAME>.*?<SW-ARRAYSIZE>\s*<VF>([^<]*)</VF>\s*</SW-ARRAYSIZE>.*?<(?:/(?!<SW-VARIABLE>)[^/]*?)SW-VARIABLE>

у вас правильно был вопросительный знак после

</SW-ARRAYSIZE>.*

, но вы пропустили его после

</SHORT-NAME>.*

.

Я думаю, вы хотите захватить только содержимое двух '. *?' S. Если это так, я бы поместил их в группы и извлекал группы в коде для работы с ними. Тогда регулярное выражение станет:

<SW-VARIABLE>\s*<SHORT-NAME>(?P<sn>[^<]*?)</SHORT-NAME>.*?<SW-ARRAYSIZE>\s*<VF>(?P<vf>[^<]*?)</VF>\s*</SW-ARRAYSIZE>.*?<(?:/(?!<SW-VARIABLE>)[^/]*?)SW-VARIABLE>

с двумя именами групп: sn и vf. demo

Ваш python код для получения названных групп станет:

matches= re.search(regex, string1)
print("shortName: ", matches.group('sn'))
print("vf: ", matches.group('vf'))
0 голосов
/ 17 февраля 2020

Кажется, я сам нашел ответ:

pattern = r'<SW-VARIABLE>\s*<SHORT-NAME>([^<]*)</SHORT-NAME>\s*<CATEGORY>[^<]*</CATEGORY>\s*<SW-ARRAYSIZE>\s*<VF>(.*)</VF>\s*</SW-ARRAYSIZE>'

print(re.findall(pattern, text))

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...