【问题标题】:Replace xml tag contents using python使用python替换xml标签内容
【发布时间】:2016-01-11 00:17:15
【问题描述】:

我有一个包含一些数据的 xml 文件。

<Emp>
<Name>Raja</Name>
<Location>
     <city>ABC</city>
     <geocode>123</geocode>
     <state>XYZ</state> 
</Location>
<sal>100</sal>
<type>temp</type> 
</Emp>

所以xml文件中的位置信息是错误的,我必须替换它。

我已经在 python 中用更正的值构造了位置信息。

variable = '''
    <Location isupdated=1>
         <city>MyCity</city>
         <geocode>10.12</geocode>
         <state>MyState</state> 
    </Location>'''

因此,位置标记应替换为新信息。有什么简单的方法可以在 python 中更新它。

我想要最终的结果数据,例如,

<Emp>
<Name>Raja</Name>
<Location isupdated=1>
         <city>MyCity</city>
         <geocode>10.12</geocode>
         <state>MyState</state>
</Location>
<sal>100</sal>
<type>temp</type> 
</Emp>

有什么想法吗??

谢谢。

【问题讨论】:

  • 我认为应该删除regex 标签,这不是正则表达式的任务。看起来像是用 XML 解析器替换节点的经典示例。
  • @SaketMittal,但是在这里我想替换位置标签本身?可能是另外一个添加到变量模板的标签。我只想删除 标签,并在其中添加变量内容。

标签: python regex xml lxml


【解决方案1】:

UPDATE - XML PARSER IMPLEMENTATION:因为替换特定的&lt;Location&gt; 标记需要修改正则表达式,所以我提供了一个基于 ElementTree 解析器的更通用和更安全的替代实现(如上所述 @ stribizhev 和@Saket Mittal)。

我必须添加一个根元素 &lt;Emps&gt;(以制作有效的 xml 文档,需要根元素),我还选择通过 &lt;city&gt; 标签过滤要编辑的位置(但可能是每个字段) :

#!/usr/bin/python
# Alternative Implementation with ElementTree XML Parser

xml = '''\
<Emps>
    <Emp>
        <Name>Raja</Name>
        <Location>
            <city>ABC</city>
            <geocode>123</geocode>
            <state>XYZ</state>
        </Location>
        <sal>100</sal>
        <type>temp</type>
    </Emp>
    <Emp>
        <Name>GsusRecovery</Name>
        <Location>
            <city>Torino</city>
            <geocode>456</geocode>
            <state>UVW</state>
        </Location>
        <sal>120</sal>
        <type>perm</type>
    </Emp>
</Emps>
'''

from xml.etree import ElementTree as ET
# tree = ET.parse('input.xml')  # decomment to parse xml from file
tree = ET.ElementTree(ET.fromstring(xml))
root = tree.getroot()

for location in root.iter('Location'):
    if location.find('city').text == 'Torino':
        location.set("isupdated", "1")
        location.find('city').text = 'MyCity'
        location.find('geocode').text = '10.12'
        location.find('state').text = 'MyState'

print ET.tostring(root, encoding='utf8', method='xml')
# tree.write('output.xml') # decomment if you want to write to file

在线可运行版代码here

以前的正则表达式实现

这是使用惰性修饰符.*? 和点所有(?s) 的可能实现:

#!/usr/bin/python

import re

xml = '''\
<Emp>
<Name>Raja</Name>
<Location>
     <city>ABC</city>
     <geocode>123</geocode>
     <state>XYZ</state>
</Location>
</Emp>'''

locUpdate = '''\
    <Location isupdated=1>
         <city>MyCity</city>
         <geocode>10.12</geocode>
         <state>MyState</state>
    </Location>'''

output = re.sub(r"(?s)<Location>.*?</Location>", r"%s" % locUpdate, xml)

print output

可以在线测试代码here

警告:如果 xml 输入中有多个 &lt;Location&gt; 标记,则正则表达式将它们全部替换为 locUpdate。你必须使用:

# (note the last ``1`` at the end to limit the substitution only to the first occurrence)
output = re.sub(r"(?s)<Location>.*?</Location>", r"%s" % locUpdate, xml, 1)

【讨论】:

  • 我在 标签之后有一些标签,如何在输出中也保留它?
  • @MagendranV 如果您测试在线implementation,则保留 之后的 标签。无论如何,如果您提供您的 xml 输入,我会检查
  • 我稍微修改了输入。请看一下
  • @MagendranV:对我来说没有任何改变,'&lt;/Location&gt;' 之后的所有内容都被保留(您可以检查修改后的代码online 的标准输出。我相信提供给正则表达式或类似的。
  • @MagendranV:我提供了一个替代实现,它使用 ElementTree 作为 XML 解析器,可以更好地控制替换。此实现(从提供的字符串或文件解析)也可以解决您上面提到的其他问题。
猜你喜欢
  • 2014-06-19
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 2022-12-08
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多