Python:在XML中将所有标签名中的连字符替换为下划线

3 投票
2 回答
2658 浏览
提问于 2025-04-17 07:23

我有一个格式不太规范的XML文件,里面的标签名有连字符,我想把这些连字符替换成下划线(这样我就可以用lxml.objectify来处理它)。我想替换所有的标签名,包括里面的子标签。

这是一个示例XML:

<job>
  <server>
    <cpu-set>
    </cpu-set>
  </server>
  <ip-routings>
  </ip-routings>
</job>

我想用一种干净的方式来转换这个XML(不使用正则表达式,而是用像lxml这样的XML库),变成这个样子:

<job>
  <server>
    <cpu_set>
    </cpu_set>
  </server>
  <ip_routings>
  </ip_routings>
</job>

有什么好的方法可以用Python来做到这一点吗?

2 个回答

1

我知道这不是Python,但对我来说,这很像Python的风格:使用Mono的C#解释器

using System.Xml.Linq;

var doc = XDocument.Load(Console.In);

foreach(var node in doc.Descendants().Reverse())
    node.ReplaceWith(new XElement(
        node.Name.Namespace + node.Name.LocalName.Replace("-","_"), 
        node.Attributes(), 
        node.Nodes()));

doc.Save(Console.Out);

这个工具有一些重要的特点,这些特点在没有现成的XML库的情况下很难实现:

  • 支持混合元素(可以包含文本子元素)
  • 保留命名空间
  • 保留属性
  • 支持所有XML 2.0的功能(比如CDATA、未解析的内容、实体引用等)
  • 还有更多类似的功能

演示:

输入文件:input.xml:

<?xml version="1.0"?>
<job xmlns:ex="test">
  <server attr1="first" attr2="second">
    <ex:cpu-set>
    </ex:cpu-set>
  </server>
  <ip-routings>
      contained <mixed/>text
  </ip-routings>
</job>

运行csharp -r:System.Xml.Linq test < input.xml的输出结果:

<?xml version="1.0" encoding="utf-8"?>
<job xmlns:ex="test">
  <server attr1="first" attr2="second">
    <ex:cpu_set />
  </server>
  <ip_routings>
      contained <mixed />text
  </ip_routings>
</job>
5

使用xpath来找到带有连字符的元素,并重新写标签:

from lxml import etree
data = """<job>
  <server>
    <cpu-set>
    </cpu-set>
  </server>
  <ip-routings>
  </ip-routings>
</job>"""
doc = etree.XML(data)
for e in doc.xpath('//*[contains(local-name(),"-")]'):
  e.tag = e.tag.replace('-','_')

print etree.tostring(doc)

结果是:

<job>
  <server>
    <cpu_set>
    </cpu_set>
  </server>
  <ip_routings>
  </ip_routings>
</job>

撰写回答