用 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# 等)。
假设我有一个 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# 等)。