2011-01-25 8 views
9

muszę przechodzić przez drzewo XML, aby dodać elementu podrzędnego, gdy wartość jest mniejsza niż 5. Na przykład ten XML mogą być modyfikowane wWłóż węzeł elementu w XML z Python/ElementTree

<?xml version="1.0" encoding="UTF-8"?> 
<A value="45"> 
    <B value="30"> 
     <C value="10"/> 
     <C value ="20"/> 
    </B> 
    <B value="15"> 
     <C value = "5" /> 
     <C value = "10" /> 
    </B> 
</A> 

to XML.

<?xml version="1.0" encoding="UTF-8"?> 
<A value="45"> 
    <B value="30"> 
     <C value="10"/>    
     <C value ="20"/> 
    </B> 
    <B value="15"> 
     <C value = "5"><D name="error"/></C> 
     <C value = "10" /> 
    </B> 
</A> 

Jak mogę to zrobić z ElementTree w Pythonie?

+0

związane: http://stackoverflow.com/questions/4788958/set-of-xml-file-recursively-with-python-elementtree – jfs

+0

Czy może istnieć więcej niż jedno 'dziecko' ? Czy rozważałeś możliwość dodania atrybutu "błąd" do elementu z problemem? –

Odpowiedz

13

Prawdopodobnie popełnił literówkę bo na przykład element błędu jest dołączany jako dziecko elementu, którego wartość wynosi 10, co nie jest mniej niż 5. Ale myślę, że jest to pomysł:

#!/usr/bin/env python 

from xml.etree.ElementTree import fromstring, ElementTree, Element 

def validate_node(elem): 
    for child in elem.getchildren(): 
     validate_node(child) 
     value = child.attrib.get('value', '') 
     if not value.isdigit() or int(value) < 5: 
      child.append(Element('D', {'name': 'error'})) 

if __name__ == '__main__': 
    import sys 
    xml = sys.stdin.read() # read XML from standard input 
    root = fromstring(xml) # parse into XML element tree 
    validate_node(root) 
    ElementTree(root).write(sys.stdout, encoding='utf-8') 
      # write resulting XML to standard output 

Biorąc to wejście:

<?xml version="1.0" encoding="UTF-8"?> 
<A value="45"> 
    <B value="30"> 
     <C value="1"/> 
     <C value="20"/> 
    </B> 
    <B value="15"> 
     <C value="5" /> 
     <C value="10" /> 
     <C value="foo" /> 
    </B> 
</A> 

to jest wyjście:

<A value="45"> 
    <B value="30"> 
     <C value="1"><D name="error" /></C> 
     <C value="20" /> 
    </B> 
    <B value="15"> 
     <C value="5" /> 
     <C value="10" /> 
     <C value="foo"><D name="error" /></C> 
    </B> 
</A> 
+0

Martwię się o to, czy pętla dogłębnie iteracyjna na nowo dodanym elemencie potomnym tutaj? na przykład. jeśli parametr for jest wykonywany z 'dla węzła na liście (tree.getroot())' i węzeł jest dodawany gdzieś podczas iteracji. – n611x007

+0

Tak więc sposobem na uruchomienie tego jest 'cat file.xml | python script.py'? Zrobiłem i działa, ale zastanawiam się, czy istnieje inny sposób. – fedorqui

2

ElementTree „s iter (lub getiterator dla Pythona < 2,7) willl powrotu rekurencyjnie wszystkie węzły w drzewie, a potem po prostu przetestować dla stanu i stworzyć SubElement:

from xml.etree import ElementTree as ET 
tree = ET.parse(input) 
for e in tree.getiterator(): 
    if int(e.get('value')) < 5: 
     ET.SubElement(e,'D',dict(name='error')) 
+2

czy dodany element zostanie poddany iteracji? Jeśli tak, to w jaki sposób mogę odróżnić nowy element od już istniejących? – n611x007

Powiązane problemy