用 lxml 覆盖 XML 中的文本

Override text in XML with lxml

假设我有一个 XML 文件,我想编辑其中的一部分。以下不起作用,可能是因为我正在编辑 child.

的副本
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 的部分以便在树中完成更改?

保存对元素的引用 reset the text:

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

对于未来的读者,任何 XML 转换、样式、重新格式化和重新构造都可以使用 XSLT(用于 [=42] 的声明性编程语言来充分甚至有效地处理=] 操纵。 Python 的 lxml 模块维护着一个 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()

决赛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# 等)。