Словарь пространства имен ElementTree не работает с find () или findall () - PullRequest
0 голосов
/ 12 июля 2020

Я озадачен тем, как сделать словарь пространства имен ElementTree и последующие вызовы find () и findall (), используя документированный sytnax :

Лучший способ поиска пример с пространством имен XML - создать словарь с вашими собственными префиксами и использовать их в функциях поиска:

ns = {'real_person': 'http://people.example.com',
  'role': 'http://characters.example.com'}

for actor in root.findall('real_person:actor', ns):
    name = actor.find('real_person:name', ns)
    print(name.text)
    for char in actor.findall('role:character', ns):
        print(' |-->', char.text)

Проблема, с которой я столкнулся, заключается в том, что я попробуйте использовать синтаксис, указанный в этом do c, передав словарь «ns» в качестве второго аргумента в find () или findall (), я получаю пустой список. Если я наберу полное пространство имен без передачи второго аргумента, он вернет все ожидаемые элементы.

Я определил свой словарь пространства имен как таковой:

ns = {'ws':'{urn:com.workday/workersync}'}

И вот ElementTree и root setup:

xmlparser = ET.parse(xmlfile)
xmlroot = xmlparser.getroot()

Вот что я получаю, когда пытаюсь использовать сокращенный синтаксис словаря, указанный в документации:

>>> xmlroot.findall('ws:Worker', ns)
[]

Просто пустой список .. . Вот что я получаю, если набираю пространство имен в вызове:

xmlroot.findall('{urn:com.workday/workersync}Worker')
[<Element '{urn:com.workday/workersync}Worker' at 0x03220A78>, <Element'{urn:com.workday/workersync}Worker' at 0x0322D8C0>]

Это возвращает ожидаемые 2 элемента в моем образце файла.

Вот что находится в верхней части моего образца файла выглядит для справки:

<?xml version="1.0" encoding="UTF-8"?>
<ws:Worker_Sync xmlns:ws="urn:com.workday/workersync" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <ws:Header>
        <ws:Version>34.0</ws:Version>
        <ws:Prior_Entry_Time>2020-07-04T21:40:25.822-07:00</ws:Prior_Entry_Time>
        <ws:Current_Entry_Time>2020-07-04T22:03:47.458-07:00</ws:Current_Entry_Time>
        <ws:Prior_Effective_Time>2020-07-04T00:00:00.000-07:00</ws:Prior_Effective_Time>
        <ws:Current_Effective_Time>2020-07-05T00:00:00.000-07:00</ws:Current_Effective_Time>
        <ws:Full_File>true</ws:Full_File>
        <ws:Document_Retention_Policy>30</ws:Document_Retention_Policy>
        <ws:Worker_Count>2</ws:Worker_Count>
    </ws:Header>
    <ws:Worker>
         *<snipped rest of XML data>*

Обрезанные данные XML содержат 2 <ws:Worker> элементов со многими дочерними элементами под ними.

Я возился с этим дольше, чем я ' Буду признателен. Мне кажется, что мне не хватает чего-то невероятно очевидного, на мой взгляд, мой код выглядит как каждый пример, который я нашел в Интернете, и пример кода в документации.

Пожалуйста, помогите!

1 Ответ

1 голос
/ 12 июля 2020

Удалите фигурные скобки из строки URI. Словарь пространства имен должен выглядеть так:

ns = {'ws': 'urn:com.workday/workersync'}

Другой вариант - использовать подстановочный знак для пространства имен. Это поддерживается для find() и findall() , так как Python 3.8 :

print(xmlroot.findall('{*}Worker'))

Вывод:

[<Element '{urn:com.workday/workersync}Worker' at 0x033E6AC8>]
...