2011-01-25 2 views
9

мне нужно пересечь дерево XML для добавления дочернего элемента, если значение меньше 5. Например, это может быть XML-модифицирован вВставьте узел для элемента в XML с 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> 

этот 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> 

Как я могу это сделать с ElementTree Python?

+0

связаны: http://stackoverflow.com/questions/4788958/set-the-value-of-xml-file-recursively-with-python-elementtree – jfs

+0

Может ли быть более одного '' child? Вы рассмотрели возможность добавления атрибута «ошибка» к элементу с проблемой? –

ответ

13

Вы, вероятно, сделал опечатку, потому что в этом примере элемент ошибки добавляется как дочерний элемент, значение которого равно 10, что не менее 5. Но я думаю, что это идея:

#!/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 

Учитывая этот вход:

<?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> 

Это является выход:

<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

Что меня беспокоит, так это то, что бы все-глубина цикла повторялась по вновь добавленному дочернему элементу? например. если for выполняется с 'для узла в списке (tree.getroot()) и узел где-то добавляется во время итерации. – n611x007

+0

Итак, способ запускать это 'cat file.xml | python script.py'? Я сделал, и это работает, но мне интересно, есть ли другой способ. – fedorqui

2

«S iter (или getiterator для Python 2.7 <)Willl рекурсивно возвращает все узлы в дереве, а затем просто проверить ваше состояние и создать 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

будет ли добавлен элемент итератором? Если да, то как я могу различать новый элемент и уже существующие? – n611x007