RegEx для разбора XML в BeautifulSoup - PullRequest
0 голосов
/ 20 мая 2019

Мне нужно проанализировать файл, в частности файл XBRL, с BeautifulSoup и анализатором XML. Однако выходные данные меняются, если я использую синтаксический анализатор LXML или синтаксический анализатор XML и не могу использовать тот же регулярный код, который я успешно использовал в синтаксическом анализаторе lxml. Я включаю вывод сценария.

Причина, по которой мне нужно использовать синтаксический анализатор XML, заключается в том, что он содержит заглавные буквы, а я использую RegeX, поскольку имена тегов различаются по файлу и содержат символ ":".

soup = BeautifulSoup(xbrl, 'xml')
soup.find_all(re.compile('ifrs-full'))
output: []

# But if I use lxml parser and the same RegeX, I get:

soup = BeautifulSoup(xbrl, 'lxml')
soup.find_all(re.compile('ifrs-full'))
output: 
[<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="Duration_Actual_PerdidasFiscales_1" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,
<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="Duration_Actual_UnusedTaxLossesMember" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,
 <ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="TrimestreAcumuladoActual" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>]

Как мне решить эту проблему?

1 Ответ

0 голосов
/ 20 мая 2019

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

<(.+?):([a-z]+)\s(contextref)(=")(.+?)"\s(decimals)(=")(.+?)"\s(unitref)(=")(.+?)">(.+?)<\/(.+?):([a-z]+)>

Если последняя запятая была желательна, мы можем просто изменить ее на:

<(.+?):([a-z]+)\s(contextref)(=")(.+?)"\s(decimals)(=")(.+?)"\s(unitref)(=")(.+?)">(.+?)<\/(.+?):([a-z]+)>,?

enter image description here

RegEx

Если это выражение нежелательно, его можно изменить или изменить в regex101.com .

RegEx Circuit

jex.im также помогает визуализировать выражения.

enter image description here

Test

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"<(.+?):([a-z]+)\s(contextref)(=\")(.+?)\"\s(decimals)(=\")(.+?)\"\s(unitref)(=\")(.+?)\">(.+?)<\/(.+?):([a-z]+)>"

test_str = ("<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref=\"Duration_Actual_PerdidasFiscales_1\" decimals=\"-3\" unitref=\"CLP\">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,\n"
    "<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref=\"Duration_Actual_UnusedTaxLossesMember\" decimals=\"-3\" unitref=\"CLP\">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,\n"
    " <ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref=\"TrimestreAcumuladoActual\" decimals=\"-3\" unitref=\"CLP\">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

Демо

Этот фрагмент показывает, как работают группы захвата:

const regex = /<(.+?):([a-z]+)\s(contextref)(=\")(.+?)\"\s(decimals)(=\")(.+?)\"\s(unitref)(=\")(.+?)\">(.+?)<\/(.+?):([a-z]+)>/gm;
const str = `<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="Duration_Actual_PerdidasFiscales_1" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,
<ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="Duration_Actual_UnusedTaxLossesMember" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>,
 <ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity contextref="TrimestreAcumuladoActual" decimals="-3" unitref="CLP">-4088611000</ifrs-full:deferredtaxrelatingtoitemschargedorcrediteddirectlytoequity>`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...