Próbuję poradzić sobie z odpowiedzią post, gdzie dostaję XML. Wynik jest zapisywany jako bajty b '':

<?xml version="1.0" encoding="utf-8"?>
<result xmlns="http://something.com/Schema/V2/Result">
    <success>false</success>
    <returnType>ERROR</returnType>
    <errors>
        <error>
            <message>Invalid signature</message>
            <code>3002</code>
        </error>
    </errors>
</result>

Kod:

from lxml import etree as et

root_node = et.fromstring(response.content)
print('{}'.format(root_node.find('.//returnType')))
return_type = root_node.find('.//returnType').text

Instrukcja drukowania zwraca brak, więc wyszukiwanie wyrzucenia tekstu ().

Jeśli czuję się przez dzieci, bo dostaję węzeł, ale z przestrzeni nazw, że nie mogę sobie poradzić.

for tag in root_node.getchildren():
    print(tag)

<Element {http://something.com/Schema/V2/Result}returnType at 0x7f6c95542648>

Jak mogę uzyskać węzły XML i ich wartości? Próbowałem odpowiadania stackoverflow na podobne problemy, ale nic nie działa. Próbowałem użycia REGEX, aby usunąć schemat i dodanie prefiksu do NS.

Edytuj: Próbowałem odpowiedzi i uzyskanie standardowego błędu, że nie mogę dostać węzłów.

    /usr/bin/python3 /home/samoa/Scripts/Python/lxml_test.py
Traceback (most recent call last):
  File "/home/samoa/Scripts/Python/lxml_test.py", line 17, in <module>
    print(root.find("returnType", root.nsmap).text)
  File "src/lxml/lxml.etree.pyx", line 1537, in lxml.etree._Element.find (src/lxml/lxml.etree.c:58520)
  File "/usr/local/lib/python3.6/dist-packages/lxml/_elementpath.py", line 288, in find
    it = iterfind(elem, path, namespaces)
  File "/usr/local/lib/python3.6/dist-packages/lxml/_elementpath.py", line 277, in iterfind
    selector = _build_path_iterator(path, namespaces)
  File "/usr/local/lib/python3.6/dist-packages/lxml/_elementpath.py", line 234, in _build_path_iterator
    raise ValueError("empty namespace prefix is not supported in ElementPath")
ValueError: empty namespace prefix is not supported in ElementPath
0
Samo A. 9 październik 2020, 15:54

1 odpowiedź

Najlepsza odpowiedź

Podaj mapę przestrzeni nazw do metody find(). Jak http://something.com/Schema/V2/Result jest domyślną przestrzenią nazwową w dokumencie, to wszystko, co musisz zrobić:

return_type_element = root_node.find('.//returnType', root_node.nsmap)

Lub:

return_type_element = root_node.find('returnType', root_node.nsmap)

Co więcej, str.format() w:

print('{}'.format(root_node.find('.//returnType')))

Jest niepotrzebne i można skrócić do:

return_type_element = root_node.find('returnType', root_node.nsmap)
print(return_type_element)

# <Element {http://something.com/Schema/V2/Result}returnType at 0x107c28bc0>

Jeśli jednak chcesz wydrukować return_type_element jako XML, użyj funkcji lxml.etree.tostring():

print(ET.tostring(return_type_element))

# b'<returnType xmlns="http://something.com/Schema/V2/Result">ERROR</returnType>\n    '

Tak więc można uzyskać swój return_type przez:

return_type = root_node.find('returnType', root_node.nsmap).text

Mój skrypt testowy to:

#!/usr/bin/env python3
from lxml import etree as ET

content = b'''<?xml version="1.0" encoding="utf-8"?>
<result xmlns="http://something.com/Schema/V2/Result">
    <success>false</success>
    <returnType>ERROR</returnType>
    <errors>
        <error>
            <message>Invalid signature</message>
            <code>3002</code>
        </error>
    </errors>
</result>
'''

root = ET.fromstring(content)
emptyns = root.nsmap[None]
print(root.find("{%s}returnType" % (emptyns)).text)

# step-by-step

root = ET.fromstring(content)
print("Root element: %s" % (root))

emptyns = root.nsmap[None]
print("Empty namespace: %s" % (emptyns))

return_type_element = root.find("{%s}returnType" % (emptyns))
print("<returnType> element: %s" % (return_type_element))
print("<returnType> element as XML: %s" % (ET.tostring(return_type_element)))

return_type = return_type_element.text
print('<returnType> text: %s' % (return_type))

# children

for element in root.getchildren():
    print("Element tag (with namespace): %s" % (element.tag))
    _, _, tag = element.tag.rpartition("}")
    print("Element tag (without namespace): %s" % (tag))

Jego wynikiem jest:

ERROR
Root element: <Element {http://something.com/Schema/V2/Result}result at 0x102f63188>
Empty namespace: http://something.com/Schema/V2/Result
<returnType> element: <Element {http://something.com/Schema/V2/Result}returnType at 0x102f630c8>
<returnType> element as XML: b'<returnType xmlns="http://something.com/Schema/V2/Result">ERROR</returnType>\n    '
<returnType> text: ERROR
Element tag (with namespace): {http://something.com/Schema/V2/Result}success
Element tag (without namespace): success
Element tag (with namespace): {http://something.com/Schema/V2/Result}returnType
Element tag (without namespace): returnType
Element tag (with namespace): {http://something.com/Schema/V2/Result}errors
Element tag (without namespace): errors
2
Georges Martin 13 październik 2020, 10:17