替换 XML 文件中的单词

Replace words in XML file

我需要编写 python 脚本来替换 xml 文件中所有出现的特定单词。我只需要替换标签中的禁用词即可。

应该替换为:

<some_xml_tag>some text REPLACE_ME some text</some_xml_tag>

这不应该:

<some_xml_tag attr="REPLACE_ME">some text</some_xml_tag>

<REPLACE_ME>some text</REPLACE_ME>

我不是正则表达式专家,但它应该可行吗?

这当然是可能的...但不要使用正则表达式,请尝试 ElementTree:https://docs.python.org/2/library/xml.etree.elementtree.html

这将使 find/replace 元素文本值比元素属性等更容易

改用 XML 解析器

使用 lxml 库的示例。这里我们使用 xpath() 搜索具有所需文本的节点,然后使用 replace():

替换它
import lxml.etree as ET

ban_word = 'REPLACE_ME'
replacement = 'HELLO'

data = """<root>
    <some_xml_tag>REPLACE_ME</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">some text</some_xml_tag>
    <REPLACE_ME>some text</REPLACE_ME>
</root>
"""

root = ET.fromstring(data)

for item in root.xpath('//*[. = "%s"]' % ban_word):
    item.text = item.text.replace(ban_word, replacement)

print ET.tostring(root)

打印:

<root>
    <some_xml_tag>HELLO</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">some text</some_xml_tag>
    <REPLACE_ME>some text</REPLACE_ME>
</root>

备注:

  • 比较不区分大小写
  • xml.etree.ElementTree 不会处理这种特殊方法,因为它仅提供 有限的 xpath 支持
  • 正如@tdelaney 在评论中指出的那样,如果您有一个要替换的单词列表,最好简单地遍历所有节点并在必要时替换文本

作为来自@alexce 的回答的 extension/alternative,底线是:您仍然可以迭代所有子元素并替换循环中的所有单词:

import lxml.etree as ET

ban_words = ['REPLACE_ME', 'Some']
replacement = 'HELLO'

data = """<root>
    <some_xml_tag>REPLACE_me</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">Some text</some_xml_tag>
    <REPLACE_ME>some text</REPLACE_ME>
</root>
"""
root = ET.fromstring(data)
# different approach using iter()
for node in root.iter():
    for word in ban_words:
        node.text = node.text.replace(word, replacement)

print ET.tostring(root)

结果也将像您的列表一样区分大小写:

<root>
    <some_xml_tag>REPLACE_me</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">HELLO text</some_xml_tag>
    <REPLACE_ME>some text</REPLACE_ME>
</root>

已更新

如果不想连接词被替换,可以用字典来匹配禁用词和替换,像这样:

import lxml.etree as ET
ban = {'REPLACE_ME': 'HELLO', 'Some': 'HELLO'}

data = """<root>
    <some_xml_tag>REPLACE_me</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">REPLACE_ME Some text</some_xml_tag>
    <REPLACE_ME>someSome Some SomeSOME text</REPLACE_ME>
</root>
"""
root = ET.fromstring(data)
# different approach using iter()
for node in root.iter():
    txt = node.text.split(" ")
    for i, t in enumerate(txt):
        if ban.get(t):
            txt[i] = ban.get(t)
    node.text = ' '.join(txt)

print ET.tostring(root)

不会替换连接词的结果,只有完全匹配才会是:

<root>
    <some_xml_tag>REPLACE_me</some_xml_tag>
    <some_xml_tag attr="REPLACE_ME">HELLO HELLO text</some_xml_tag>
    <REPLACE_ME>someSome HELLO SomeSOME text</REPLACE_ME>
</root>