替换 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>
我需要编写 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>