2015-09-28 2 views
1

Скажем, у меня есть XML-файл, и я хочу отредактировать его части. Следующие не работают, возможно потому, что я редактирую копию ребенка.Переопределить текст в XML с помощью lxml

from lxml import etree as et 

tree = et.parse(p_my_xml)  
root = tree.getroot()  

for child in root: 
    for entry in child.getchildren(): 

    first_part = entry.getchildren()[1].text 
    second_part = entry.getchildren()[2].text 

    if first_part == 'some_condition' 
     second_part = 'something_else' 

tree.write(p_my_xml, pretty_print=True) 

Как правильно изменить части XML, чтобы изменения были выполнены в дереве?

+1

Строки ** неизменяемы **, так что даже если 'getchildren' действительно дает вам копию (я не знаю, в любом случае, хотя я и не подозреваю) это никогда не сработает. Попробуйте присвоить атрибут 'text', т. Е. Используя' second_part = entry.getchildren() [2] ', а затем' second_part.text = 'something_else''. – jonrsharpe

ответ

2

Сохранить ссылку на элемент и reset the text:

second_elm = entry.getchildren()[2] 
if first_part == 'some_condition' 
    second_elm.text = 'something_else' 
2

Для будущих читателей, любое преобразование XML, моделирование, переформатирования и реструктуризации может быть адекватно и даже эффективно обращаться с XSLT, декларативной язык программирования, используемый для обработки XML. И модуль lxml Python поддерживает XSLT-процессор.

См ниже обобщен пример, используя потребности Op в:

Оригинальный XML

<?xml version="1.0" encoding="UTF-8"?> 
<root>  
    <child> 
     <entry1>some text</entry1> 
     <entry2>other text</entry2>   
    </child> 
    <child> 
     <entry1>some text</entry1> 
     <entry2>other text</entry2>   
    </child> 
</root> 

скрипт XSLT

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="root"> 
<root> 
    <xsl:for-each select="//child"> 
     <child> 
      <xsl:copy-of select="entry1"/> 
      <xsl:if test="entry1='some text'"> 
       <entry2>some new text</entry2> 
      </xsl:if> 
     </child> 
    </xsl:for-each> 
</root> 
</xsl:template> 

</xsl:transform> 

Python скрипт

import os 
import lxml.etree as ET 

cd = os.path.dirname(os.path.abspath(__file__)) 

dom = ET.parse(os.path.join(cd, 'Original.xml')) 
xslt = ET.parse(os.path.join(cd, 'XSLTScript.xsl')) 
transform = ET.XSLT(xslt) 
newdom = transform(dom) 

tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True) 

xmlfile = open(os.path.join(cd, 'Final.xml'),'wb') 
xmlfile.write(tree_out) 
xmlfile.close() 

Final XML

<?xml version='1.0' encoding='UTF-8'?> 
<root> 
    <child> 
    <entry1>some text</entry1> 
    <entry2>some new text</entry2> 
    </child> 
    <child> 
    <entry1>some text</entry1> 
    <entry2>some new text</entry2> 
    </child> 
</root> 

Хотя выше может показаться слишком сложны и не Pythonic один вкладыш, пожалуйста, обратите внимание, что может быть случай, когда вам требуется сложный, запутанный реструктуризации XML, где вы может использовать рекурсивный язык форматирования XSLT, а не запускать сложные циклы итераций в объектно-ориентированном программировании (Python, PHP, Java, C# и т. д.).

+0

Замечательно знать. Спасибо @Parfait! –

Смежные вопросы