Что-то не так с моим скриптом или файлом XML? Я использую ElementTree, чтобы получить дочерние атрибуты - PullRequest
0 голосов
/ 05 мая 2020

Это сокращенная версия файла XML, который я пытаюсь разобрать:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TipsContents xmlns="http://www.avendasys.com/tipsapiDefs/1.0">
  <TipsHeader exportTime="Mon May 04 20:05:47 SAST 2020" version="6.8"/>
  <Endpoints>
    <Endpoint macVendor="SHENZHEN RF-LINK TECHNOLOGY CO.,LTD." macAddress="c46e7b2939cb" status="Known">
      <EndpointProfile updatedAt="May 04, 2020 10:02:21 SAST" profiledBy="Policy Manager" addedAt="Mar 04, 2020 17:31:53 SAST" fingerprint="{}" conflict="false" name="Windows" family="Windows" category="Computer" staticIP="false" ipAddress="xxx.xxx.xxx.xxx"/>
      <EndpointTags tagName="Username" tagValue="xxxxxxxx"/>
      <EndpointTags tagName="Disabled Reason" tagValue="IS_ACTIVE"/>
    </Endpoint>
     </Endpoints>
  <TagDictionaries>
    <TagDictionary allowMultiple="false" mandatory="true" defaultValue="false" dataType="Boolean" attributeName="DOMAIN-MACHINES" entityName="Endpoint"/>
    <TagDictionary allowMultiple="false" mandatory="true" defaultValue="true" dataType="Boolean" attributeName="IS_ACTIVE" entityName="Endpoint"/>
    <TagDictionary allowMultiple="true" mandatory="false" dataType="String" attributeName="Disabled Reason" entityName="Endpoint"/>
    <TagDictionary allowMultiple="false" mandatory="false" dataType="String" attributeName="Username" entityName="Endpoint"/>
  </TagDictionaries>
</TipsContents>

Я запускаю следующий скрипт:

import xml.etree.ElementTree as ET 
f = open("Endpoint-5.xml", 'r')
tree = ET.parse(f)
root = tree.getroot()

Это то, что я получаю выглядят так:


In [8]: root = tree.getroot()                                                                                                                                                                               

In [9]: root.findall('.')                                                                                                                                                                                   
Out[9]: [<Element '{http://www.avendasys.com/tipsapiDefs/1.0}TipsContents' at 0x10874b410>]

In [10]: root.findall('./TipsHeader')                                                                                                                                                                       
Out[10]: []

In [11]: root.findall('./TipsContents')                                                                                                                                                                     
Out[11]: []

In [15]: root.findall('{http://www.avendasys.com/tipsapiDefs/1.0}TipsContents//Endpoints/Endpoint/EndpointProfile')                                                                                         
Out[15]: []

Я следил за этим: https://docs.python.org/3/library/xml.etree.elementtree.html#example среди других руководств, но, похоже, я не получил вывода.

Я пробовал from lxml import html

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

        tree = html.fromstring(html=f)
        updatedAt = tree.xpath("//TipsContents/Endpoints/Endpoint/EndpointProfile/@updatedAt")
        name = tree.xpath("//TipsContents/Endpoints/Endpoint/EndpointProfile/@name")
        category = tree.xpath("//TipsContents/Endpoints/Endpoint/EndpointProfile/@category")
        tagValue = tree.xpath("//TipsContents/Endpoints/Endpoint/EndpointTags[@tagName = 'Username']/@tagValue") 
        active = tree.xpath("//TipsContents/Endpoints/Endpoint/EndpointTags[@tagName = 'Disabled Reason']/@tagValue")
        print("Name:",name)

Приведенная выше попытка также ничего не возвращает.

Я могу проанализировать документ XML из API и успешно использовать вторую попытку, но когда я делаю это из локального файла, я не получаю результатов.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 10 мая 2020

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

Один из способов сделать это - определить словарь пространств имен ( ярлык : full_name ), в вашем случае:

ns = {'tips': 'http://www.avendasys.com/tipsapiDefs/1.0'}

Затем, используя findall :

  • , используйте соответствующий ярлык перед именем элемента (и ':'),
  • передайте словарь пространства имен в качестве второго аргумента.

Код для этого:

for elem in root.findall('./tips:TipsHeader', ns):
    print(elem.attrib)

Результат для вашего входного образца:

{'exportTime': 'Mon May 04 20:05:47 SAST 2020', 'version': '6.8'}

Что касается root .findall ('./ TipsContents') , он вернет пустой список, даже если вы укажете пространство имен, как указано выше.

Причина в том, что TipsContents - это имя узла root, тогда как вы пытаетесь найти элемент с таким же именем ниже в дереве XML, но не содержит такого элемента.

Если вы хотите получить доступ к атрибутам элемента root вы можете запустить:

print(root.attrib)

, но чтобы получить нечто большее, чем пустой словарь, вы должны добавить некоторые атрибуты к элементу root (пространство имен не является атрибутом).

...