2014-02-13 2 views
4

для этого XMLполучить все родители XML узла с помощью питона

<Departments orgID="123" name="xmllist"> 
    <Department> 
     <orgID>124</orgID> 
     <name>A</name> 
     <type>type a</type> 
     <status>Active</status> 
      <Department> 
       <orgID>125</orgID> 
       <name>B</name> 
       <type>type b</type> 
       <status>Active</status> 
       <Department> 
        <orgID>126</orgID> 
        <name>C</name> 
        <type>type c</type> 
        <status>Active</status> 
       </Department> 
      </Department> 
    </Department> 
    <Department> 
     <orgID>109449</orgID> 
     <name>D</name> 
     <type>type d</type> 
     <status>Active</status> 
    </Department> 
</Departments> 

Как я могу получить все родители узла с помощью lxmletree в питона.

Ожидаемый результат: ввод orgid = 126, он будет возвращать все родители, как,

{'A':124,'B':125,'C':126} 

ответ

5

Использование lxml и XPath:

>>> s = ''' 
... <Departments orgID="123" name="xmllist"> 
...  <Department> 
...   <orgID>124</orgID> 
...   <name>A</name> 
...   <type>type a</type> 
...   <status>Active</status> 
...    <Department> 
...     <orgID>125</orgID> 
...     <name>B</name> 
...     <type>type b</type> 
...     <status>Active</status> 
...     <Department> 
...      <orgID>126</orgID> 
...      <name>C</name> 
...      <type>type c</type> 
...      <status>Active</status> 
...     </Department> 
...    </Department> 
...  </Department> 
...  <Department> 
...   <orgID>109449</orgID> 
...   <name>D</name> 
...   <type>type d</type> 
...   <status>Active</status> 
...  </Department> 
... </Departments> 
... ''' 

Использование ancestor-or-self оси, вы можете найти сам узел, родитель, дедушка и бабушка, ...

>>> import lxml.etree as ET 
>>> root = ET.fromstring(s) 
>>> for target in root.xpath('.//Department/orgID[text()="126"]'): 
...  d = { 
...   dept.find('name').text: int(dept.find('orgID').text) 
...   for dept in target.xpath('ancestor-or-self::Department') 
...  } 
...  print(d) 
... 
{'A': 124, 'C': 126, 'B': 125} 
+0

Спасибо, и что, если я хочу включить orgID = 123 и имя = XMLList в г? – fledgling

+1

@Nishant, 'для дептов в target.xpath ('ancestor-or-self :: Departments'): d [depts.get ('name')] = depts.get ('orgID')' перед 'print' заявление. – falsetru

+0

Спасибо, но вывод, кажется, неупорядочен, есть ли способ сделать это заказанным? Здесь мы получаем {'A': 124, 'C': 126, 'B': 125} можем ли мы получить его как {'A': 124, 'B': 125, 'C': 126} ?? – fledgling

0

Используйте метод lxml iterancestors().

from lxml import etree 

doc = etree.fromstring(xml) 
rval = {} 
for org in doc.xpath('//orgID[text()="126"]'): 
    for ancestor in org.iterancestors('Department'): 
     id=ancestor.find('./orgID').text 
     name=ancestor.find('./name').text 
     rval[name]=id 

print rval 

выход:

{'A': '124', 'C': '126', 'B': '125'} 

Если вы на самом деле пытается сохранить порядок элементов, то вы не можете использовать Dict, потому что вы не можете контролировать порядок ключей в Словаре. Вы должны будете использовать OrderedDict или просто и массив кортежей:

doc = etree.fromstring(xml) 
a = [] 
for org in doc.xpath('//orgID[text()="126"]'): 
    for ancestor in org.iterancestors(): 
     if ancestor.find('./orgID') is not None: 
      id=ancestor.find('./orgID').text 
      name=ancestor.find('./name').text 
     elif ancestor.get('orgID'): 
      id=ancestor.get('orgID') 
      name=ancestor.get('name') 
     else: 
      continue 

     print id,name 
     a.append((name,id)) 

print "In order of discovery:\n ", a 
print "From root to child\n ", [x for x in reversed(a)] 
print "dict keys are not sorted\n ", dict(a) 

Выход:

126 C 
125 B 
124 A 
123 xmllist 
In order of discovery: 
    [('C', '126'), ('B', '125'), ('A', '124'), ('xmllist', '123')] 
From root to child 
    [('xmllist', '123'), ('A', '124'), ('B', '125'), ('C', '126')] 
dict keys are not sorted 
    {'A': '124', 'xmllist': '123', 'C': '126', 'B': '125'} 
Смежные вопросы