tree = etree.fromstring (bytes (xml, encoding = 'utf-8')) TypeError: кодировка без строкового аргумента - PullRequest
0 голосов
/ 13 февраля 2020

Я хотел бы написать функцию, которая позволит мне извлечь значение атрибута "fm c" и текст внутри части "tag". Я хотел бы использовать решение регулярных выражений.

<?xml version = "1.0" encoding="UTF-8" standalone="yes" ?>
<corpus>
    <ver id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" type="discours">
        <part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro.</part>
    </ver>
    <ver id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motives">
        <part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.</part>
    </ver>
    <ver id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
        <part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.</part>
    </ver>
    <ver id="897" etude="EC3_Elec" elec="oui" niveau="4" critere="4.1" origine="TR" type="discours" fmc="obstacle">
        <part code="EC3_Elec_TR2_1">Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,</part>
        <iwer>Çava influencer la demande pour ce type de solution c'est ça ?</iwer>
        <part code="EC3_Elec_TR2_1">Je pense oui</part>
    </ver>
</corpus>

Поэтому я изменил эту функцию, чтобы соответствовать моим данным в соответствии с ответами выше

код

def review_extractor(xml, category='verbatim', do_lower=False):
    """
    Extract review and label
    """
    # use lxml...

    # parse the xml snippet into an object tree
    tree = etree.fromstring(bytes(xml, encoding='utf-8'))
    # find all elements that have "fmc" attribute
    for e in tree.findall(".//*[@fmc]"):
        label = e.xpath("./@fmc")[0]
        for c in e.getchildren("./part"):
            # print value of "fmc" attribute and text of child element
            print(f"{label:15}{c.text}")
            # 
        return label, c.text

Так Для моего примера функция должна возвращать это (обзор перед меткой):

Label      review_text
motivation Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.

condition Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.

obstacle Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,

obstacle Je pense oui

Ответы [ 6 ]

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

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

xml_string = """<?xml version = "1.0" encoding="UTF-8" standalone="yes" ?>
<corpus>
    <ver id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" type="discours">
        <part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro.</part>
    </ver>
    <ver id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motives">
        <part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.</part>
    </ver>
    <ver id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
        <part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.</part>
    </ver>
    <ver id="897" etude="EC3_Elec" elec="oui" niveau="4" critere="4.1" origine="TR" type="discours" fmc="obstacle">
        <part code="EC3_Elec_TR2_1">Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,</part>
        <iwer>Çava influencer la demande pour ce type de solution c'est ça ?</iwer>
        <part code="EC3_Elec_TR2_1">Je pense oui</part>
    </ver>
</corpus>"""

import xml.etree.ElementTree as ET
tree = ET.fromstring(xml_string)

for i in tree.findall('ver'):
    fmc = i.attrib.get("fmc")
    if fmc is None:
        continue
    for p in i.findall("part"):
        print(fmc, p.text)

Вывод

motives Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.
condition Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.
obstacle Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,
obstacle Je pense oui

если вы хотите использовать выражения xpath, вы можете немного упростить его

for i in tree.findall('ver[@fmc]'):
    for p in i.findall('part'):
        print(i.attrib['fmc'], p.text)
0 голосов
/ 13 февраля 2020

Почему бы вам не использовать lxml для анализа XML? ИМХО, гораздо проще позволить l xml разобрать xml и перемещаться по результирующему дереву элементов, используя, например, XPath, чтобы найти нужные вещи.

# install lxml
pip3 install lxml
# xml snippet
xml = """\
<?xml version = "1.0" encoding="UTF-8" standalone="yes" ?>
<corpus>
    <ver id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" type="discours">
        <part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro.</part>
    </ver>
    <ver id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motives">
        <part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.</part>
    </ver>
    <ver id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
        <part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.</part>
    </ver>
    <ver id="897" etude="EC3_Elec" elec="oui" niveau="4" critere="4.1" origine="TR" type="discours" fmc="obstacle">
        <part code="EC3_Elec_TR2_1">Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,</part>
        <iwer>Çava influencer la demande pour ce type de solution c'est ça ?</iwer>
        <part code="EC3_Elec_TR2_1">Je pense oui</part>
    </ver>
</corpus>
"""

Тогда этот код выполняет трюк!

# use lxml...
from lxml import etree
# parse the xml snippet into an object tree
tree = etree.fromstring(bytes(xml, encoding='utf-8'))
# find all elements that have "fmc" attribute
for e in tree.findall(".//*[@fmc]"):
    label = e.xpath("./@fmc")[0]
    for c in e.findall("./part"):
        # print value of "fmc" attribute and text of all <part> elements
        print(f"{label:15}{c.text}")

Выход:

motives        Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.
condition      Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.
obstacle       Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,
obstacle       Je pense oui
0 голосов
/ 13 февраля 2020

Эта работа лучше подходит для парсера XML. Я использую untangle из репозитория PyPI:

import untangle

xml = """<?xml version = "1.0" encoding="UTF-8" standalone="yes" ?>
<corpus>
    <ver id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" type="discours">
        <part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro.</part>
    </ver>
    <ver id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motives">
        <part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.</part>
    </ver>
    <ver id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
        <part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.</part>
    </ver>
    <ver id="897" etude="EC3_Elec" elec="oui" niveau="4" critere="4.1" origine="TR" type="discours" fmc="obstacle">
        <part code="EC3_Elec_TR2_1">Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,</part>
        <iwer>Çava influencer la demande pour ce type de solution c'est ça ?</iwer>
        <part code="EC3_Elec_TR2_1">Je pense oui</part>
    </ver>
</corpus>
"""

doc = untangle.parse(xml)
for ver in doc.corpus.ver:
    if ver['fmc'] is None: continue
    print(f"id={ver['id']}, fmc={ver['fmc']}")
    for part in ver.part:
        print(f"   part={part.cdata}")

Отпечатки:

id=30, fmc=motives
   part=Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.
id=54, fmc=condition
   part=Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.
id=897, fmc=obstacle
   part=Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,
   part=Je pense oui
0 голосов
/ 13 февраля 2020

Regex действительно неправильное решение для этого, но это может сработать:

fmc="(.*?)".*?<part.*?>(.*?)</part>

https://regex101.com/r/M7LJLU/1

И желаемый результат будет в \1 и \2.

0 голосов
/ 13 февраля 2020

Вы можете попробовать регулярное выражение:

<([a-zA-Z0-9]+)[^\/]*?fmc=([\'\"])(.*?)\2.*?>[\s\n\r]*<([a-zA-Z0-9]+).*?>(.*?)</\4>

Как видно здесь .

Полный код выглядит следующим образом:

import re

f = """<corpus>
    <ver id="18" etude="EC1_Elec" elec="oui" niveau="1" critere="1.3" type="discours">
        <part code="EC1_Elec_IW04_0">Ça existe sur des gros parcs Hlm mais c'est macro.</part>
    </ver>
    <ver id="30" etude="EC1_Elec" elec="oui" niveau="2" critere="" origine="IW" type="discours" fmc="motivation">
        <part code="EC1_Elec_IW01_0">Avant 75 on n'a pas isolé puis après, au fur et à mesure des règlementations.</part>
    </ver>
    <ver id="54" etude="EC1_Elec" elec="oui" niveau="1" critere="" origine="IW" type="discours" fmc="condition">
        <part code="EC1_Elec_IW10_0">Le deuxième boitier, il est où ? s'il y en a un qui est à l'intérieur et qui remplace un bout de l'isolation, il est caché OK.</part>
    </ver>
    <ver id="897" etude="EC3_Elec" elec="oui" niveau="4" critere="4.1" origine="TR" type="discours">
        <part code="EC3_Elec_TR2_1">Avec l'économie d'énergie, on va imposer de plus en plus d'automatismes,</part>
        <iwer>Çava influencer la demande pour ce type de solution c'est ça ?</iwer>
        <part code="EC3_Elec_TR2_1">Je pense oui</part>
    </ver>
</corpus>"""

regex = r'<([a-zA-Z0-9]+)[^\/]*?fmc=([\'\"])(.*?)\2.*?>[\s\n\r]*<([a-zA-Z0-9]+).*?>(.*?)</\4>'

matches = re.findall(regex, f)

for x in matches:
    print(x[2] + " " + x[4])
0 голосов
/ 13 февраля 2020

Попробуйте это /fmc(.*?)+=(.*?)+\"(.+?)\"/g

...