Python: замена строк (замена дефисов подчеркиванием) во всех именах тегов внутри XML - PullRequest
3 голосов
/ 30 ноября 2011

У меня не очень хорошо сформированный XML с дефисами внутри имен тегов, который я хочу заменить на подчеркивание (чтобы иметь возможность работать с lxml.objectify).Я хочу заменить ВСЕ имена тегов, включая вложенные дочерние элементы.

Пример XML:

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

Я хочу преобразовать этот XML чистым способом (без регулярных выражений, но с использованием XML-библиотеки, например lxml) в этот:

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

Каким был бы питонский и чистый способ сделать это?

Ответы [ 2 ]

4 голосов
/ 30 ноября 2011

Используйте 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>
1 голос
/ 30 ноября 2011

Я знаю, что это не python, но для меня это pythonic: C # с интерпретатором csharp из mono :

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>
...