【问题标题】:Override text in XML with lxml使用 lxml 覆盖 XML 中的文本
【发布时间】:2015-09-28 15:25:10
【问题描述】:

假设我有一个 XML 文件,我想编辑它的一部分。以下不起作用,可能是因为我正在编辑一个孩子的副本。

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 以便在树中完成更改?

【问题讨论】:

  • 字符串是不可变的,所以即使getchildren确实给了你一个副本(我不知道这两种方式,虽然我怀疑不是)这永远不会奏效.尝试分配回text 属性,即使用second_part = entry.getchildren()[2],然后使用second_part.text = 'something_else'

标签: python python-3.x lxml


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    对于未来的读者,任何 XML 转换、样式、重新格式化和重新结构都可以使用XSLT(用于 XML 操作的声明性编程语言)充分甚至有效地处理。而 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>
    

    虽然上述内容可能看起来过于复杂,而不是 Python 风格的单行代码,但请注意,在某些情况下,您可能需要进行复杂、错综复杂的 XML 重组,在这种情况下,您可以利用 XSLT 的递归、模板格式化语言,而不是运行复杂的迭代循环面向对象编程(Python、PHP、Java、C# 等)。

    【讨论】:

    • 很高兴知道。谢谢@Parfait!
    猜你喜欢
    • 2015-08-04
    • 2017-10-22
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 2022-06-23
    • 1970-01-01
    相关资源
    最近更新 更多