Выберите несколько строк из файла XML с помощью Python - PullRequest
1 голос
/ 29 мая 2020

У меня есть XML, который я хочу экспортировать несколько строк, основанный на содержимом атрибута 1.

Мой файл выглядит так:

<Root>
  <First_Level_Node>
    <Element_Name>
      <attribute1>1</attribute1>
      <attribute2>2</attribute2>
      <attribute3>3</attribute3>
      <attribute4>4</attribute4>
      <attribute5>5</attribute5>
      <attribute6>6</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>41</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random value</attribute5>
      <attribute6>18th Jun 2014  07:09:18 GMT</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>42</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>23rd Jul 2014  02:47:10 GMT</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>43</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>08th Nov 2014  23:53:31 GMT</attribute6>
    </Element_Name>
  </First_Level_Node>
</Root>

И на основе значения атрибут 1, я хочу получить все строки из этого элемента. Например, мне нужен атрибут 1 = 42 или атрибут 1 = 43, поэтому результат будет примерно таким:

<Root>
  <First_Level_Node>
    <Element_Name>
      <attribute1>42</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>23rd Jul 2014  02:47:10 GMT</attribute6>
    </Element_Name>
    <Element_Name>
      <attribute1>43</attribute1>
      <attribute2></attribute2>
      <attribute3>NO</attribute3>
      <attribute4>42</attribute4>
      <attribute5>random</attribute5>
      <attribute6>08th Nov 2014  23:53:31 GMT</attribute6>
    </Element_Name>
  </First_Level_Node>
</Root>

Я хочу использовать для этого Python.

Я пытался использовать ElementTree, но безуспешно. Это то, что я пробовал до сих пор

with open("output.xml", 'r') as f3:
        root = ET.parse(f3)

    tree=root.getroot()
    with open("list_xxx", 'r') as f2:
        for line in f2:
            line = line.rstrip()
            print (line)
            #get all subnet nodes containing certain ManagedElementId
            subnet_path = './/*[attribute1="{0}"]'
            subnet_path = subnet_path.format(line)
            for subnet in tree.findall(subnet_path):
                #reconstruct subnet node:
                parent = ET.Element(subnet.tag, attrib=subnet.attrib)
                #path to find all ManagedElement containing certain ManagedElementId
                content_path = ".//*[attribute1='{0}']".format(line)
                print (content_path)

                #append all ManagedElement found to the new subnet:
                for content in subnet.findall(content_path):
                    parent.append(content)
                #print new subnet:
                print (ET.tostring(parent))

И список xxx имеет значения атрибута 1, которые я ищу:

41
42

Ответы [ 2 ]

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

Вы уже предварительно выбрали элементы Element_Name с указанным содержимым attribute1 (41 и 42). Нет необходимости повторно выбирать их во второй раз, в результате чего весь элемент Element_Name возвращается findall().

Вам просто нужно выбрать дочерние элементы attribute1 в этот момент .

Следовательно, если вы измените

content_path = ".//*[attribute1='{0}']".format(line)

на

 content_path = "attribute1"

, ваша программа напечатает:

41
attribute1
b'<Element_Name><attribute1>41</attribute1>\n      </Element_Name>'
42
attribute1
b'<Element_Name><attribute1>42</attribute1>\n      </Element_Name>'
0 голосов
/ 29 мая 2020

Использование l xml и xpath должно упростить задачу:

from lxml import etree

dat = """[your xml snippet above]"""
doc = etree.fromstring(dat)

targets = doc.xpath('//Element_Name[not(attribute1="42" or attribute1="43")]')
#the xpath expression above selects all ElementName nodes which do NOT meet your requirements
for target in targets:
    target.getparent().remove(target) #once an unnecessary element is selected, you go up to the parent and remove the unnecessary element
print(etree.tostring(doc).decode())

Результат - это ваш желаемый результат.

...