Python xml минидом. создать <text>некоторый текст </text> элемент - PullRequest
9 голосов
/ 03 февраля 2009

У меня есть следующий код.

from xml.dom.minidom import Document

doc = Document()

root = doc.createElement('root')
doc.appendChild(root)
main = doc.createElement('Text')
root.appendChild(main)

text = doc.createTextNode('Some text here')
main.appendChild(text)

print doc.toprettyxml(indent='\t')

Результат:

<?xml version="1.0" ?>
<root>
    <Text>
        Some text here
    </Text>
</root>

Это все прекрасно и прекрасно, но что если я хочу, чтобы вывод выглядел так?

<?xml version="1.0" ?>
<root>
    <Text>Some text here</Text>
</root>

Можно ли это легко сделать?

Orjanp ...

Ответы [ 6 ]

7 голосов
/ 03 февраля 2009

Можно ли это легко сделать?

Это зависит от того, какое именно правило вы хотите, но, как правило, нет, вы получаете небольшой контроль над симпатичной печатью. Если вам нужен конкретный формат, вам, как правило, придется написать свой собственный ходок.

Параметр DOM Level 3 LS format-pretty-print в pxdom очень близок к вашему примеру. Его правило состоит в том, что если элемент содержит только один TextNode, лишние пробелы добавляться не будут. Однако он (в настоящее время) использует два пробела для отступа, а не четыре.

>>> doc= pxdom.parseString('<a><b>c</b></a>')
>>> doc.domConfig.setParameter('format-pretty-print', True)
>>> print doc.pxdomContent
<?xml version="1.0" encoding="utf-16"?>
<a>
  <b>c</b>
</a>

(Настройте кодировку и формат вывода для любого типа сериализации, которую вы делаете.)

Если это правило, которое вы хотите, и вы можете с ним покончить, вы также можете использовать Element.writexml для minidom, например:

>>> from xml.dom import minidom
>>> def newwritexml(self, writer, indent= '', addindent= '', newl= ''):
...     if len(self.childNodes)==1 and self.firstChild.nodeType==3:
...         writer.write(indent)
...         self.oldwritexml(writer) # cancel extra whitespace
...         writer.write(newl)
...     else:
...         self.oldwritexml(writer, indent, addindent, newl)
... 
>>> minidom.Element.oldwritexml= minidom.Element.writexml
>>> minidom.Element.writexml= newwritexml

Применяются все обычные предостережения о вреде мартышек.

2 голосов
/ 19 августа 2009

Я искал в точности то же самое, и наткнулся на этот пост. (отступ, предоставленный в xml.dom.minidom, сломал другой инструмент, который я использовал для манипулирования XML, и мне нужно было сделать отступ). Я попробовал принятое решение на несколько более сложном примере, и это было результатом:

In [1]: import pxdom

In [2]: xml = '<a><b>fda</b><c><b>fdsa</b></c></a>'

In [3]: doc = pxdom.parseString(xml)

In [4]: doc.domConfig.setParameter('format-pretty-print', True)

In [5]: print doc.pxdomContent
<?xml version="1.0" encoding="utf-16"?>
<a>
  <b>fda</b><c>
    <b>fdsa</b>
  </c>
</a>

Прекрасно напечатанный XML не отформатирован правильно, и я не слишком доволен патчами обезьян (т.е. я едва знаю, что это значит, и понимаю, что это плохо), поэтому я искал другое решение.

Я записываю вывод в файл, чтобы я мог использовать программу xmlindent для Ubuntu ($ sudo aptitude install xmlindent). Поэтому я просто записываю неотформатированный файл, а затем вызываю xmlindent из программы python:

from subprocess import Popen, PIPE
Popen(["xmlindent", "-i", "2", "-w", "-f", "-nbe", file_name], 
      stderr=PIPE, 
      stdout=PIPE).communicate()

Ключ -w вызывает перезапись файла, но досадно оставляет имя, например. "myfile.xml ~", который вы, вероятно, захотите удалить. Другие переключатели предназначены для правильного форматирования (для меня).

P.S. xmlindent - это средство форматирования потока, т.е. вы можете использовать его следующим образом:

cat myfile.xml | xmlindent > myfile_indented.xml

Так что вы можете использовать его в скрипте Python без записи в файл, если вам нужно.

1 голос
/ 27 августа 2012

Это можно сделать с помощью toxml (), используя регулярные выражения, чтобы привести все в порядок.

>>> from xml.dom.minidom import Document
>>> import re
>>> doc = Document()
>>> root = doc.createElement('root')
>>> _ = doc.appendChild(root)
>>> main = doc.createElement('Text')
>>> _ = root.appendChild(main)
>>> text = doc.createTextNode('Some text here')
>>> _ = main.appendChild(text)
>>> out = doc.toxml()
>>> niceOut = re.sub(r'><', r'>\n<', re.sub(r'(<\/.*?>)', r'\1\n', out))
>>> print niceOut
<?xml version="1.0" ?>
<root>
<Text>Some text here</Text>
</root>
0 голосов
/ 07 апреля 2015

Самый простой способ сделать это - использовать prettyxml и удалить \ n и \ t внутри тегов. Таким образом, вы сохраните свой отступ, как вам требуется в вашем примере.

xml_output = doc.toprettyxml() nojunkintags = re.sub('>(\n|\t)</', '', xml_output) print nojunkintags

0 голосов
/ 25 марта 2010

Это решение сработало для меня без необходимости исправления или прекращения использования минидома:

from xml.dom.ext import PrettyPrint
from StringIO import StringIO

def toprettyxml_fixed (node, encoding='utf-8'):
    tmpStream = StringIO()
    PrettyPrint(node, stream=tmpStream, encoding=encoding)
    return tmpStream.getvalue()

http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/#best-solution

0 голосов
/ 08 марта 2009

Пакет pyxml предлагает простое решение этой проблемы с помощью функции xml.dom.ext.PrettyPrint (). Он также может печатать в дескриптор файла.

Но пакет pyxml больше не поддерживается.

Эрджан Петтерсен

...