web-dev-qa-db-ja.com

XML文字列の空白を削除します

Python 2.6のXML文字列の空白と改行を削除するにはどうすればよいですか?次のパッケージを試しました:

etree:このスニペットは元の空白を保持します:

xmlStr = '''<root>
    <head></head>
    <content></content>
</root>'''

xmlElement = xml.etree.ElementTree.XML(xmlStr)
xmlStr = xml.etree.ElementTree.tostring(xmlElement, 'UTF-8')
print xmlStr

methodパラメーターを提供するPython 2.7)は使用できません。

ミニダム:まったく同じ:

xmlDocument = xml.dom.minidom.parseString(xmlStr)
xmlStr = xmlDocument.toprettyxml(indent='', newl='', encoding='UTF-8')
22
desolat

最も簡単な解決策は、おそらく lxml を使用することです。ここで、要素間の空白を無視するようにパーサーオプションを設定できます。

_>>> from lxml import etree
>>> parser = etree.XMLParser(remove_blank_text=True)
>>> xml_str = '''<root>
>>>     <head></head>
>>>     <content></content>
>>> </root>'''
>>> elem = etree.XML(xml_str, parser=parser)
>>> print etree.tostring(elem)
<root><head/><content/></root>
_

これはおそらくあなたのニーズには十分でしょうが、安全のためにいくつかの警告があります:

これにより、要素間の空白ノードが削除され、コンテンツが混在する要素内の空白ノードが削除されなくなります。

_>>> elem = etree.XML('<p> spam <a>ham</a> <a>eggs</a></p>', parser=parser)
>>> print etree.tostring(elem)
<p> spam <a>ham</a> <a>eggs</a></p>
_

テキストノードの先頭または末尾の空白は削除されません。ただし、状況によっては、混合コンテンツから空白ノードが削除されます。パーサーがそのレベルで非空白ノードをまだ検出していない場合です。

_>>> elem = etree.XML('<p><a> ham</a> <a>eggs</a></p>', parser=parser)
>>> print etree.tostring(elem)
<p><a> ham</a><a>eggs</a></p>
_

それを望まない場合は、_xml:space="preserve"_を使用できます。これは尊重されます。別のオプションは、dtdを使用し、etree.XMLParser(load_dtd=True)を使用することです。ここで、パーサーはdtdを使用して、どの空白ノードが重要であるかを判別します。

それ以外は、不要な空白を削除する独自のコードを作成する必要があります(子孫を繰り返し、必要に応じて、空白のみを含む_.text_および_.tail_プロパティをNoneまたは空の文字列)

37
Steven

Lxmlを使いたくなかったので、すぐに思いついたものを次に示します。

from xml.dom import minidom
from xml.dom.minidom import Node

def remove_blanks(node):
    for x in node.childNodes:
        if x.nodeType == Node.TEXT_NODE:
            if x.nodeValue:
                x.nodeValue = x.nodeValue.strip()
        Elif x.nodeType == Node.ELEMENT_NODE:
            remove_blanks(x)

xml = minidom.parse('file.xml')
remove_blanks(xml)
xml.normalize()
with file('file.xml', 'w') as result:
    result.write(xml.toprettyxml(indent = '  '))

これは、XMLファイルを他の方法では壊れたインデントで再インデントするだけで本当に必要でした。 preserveディレクティブを尊重しませんが、正直なところ、XMLを処理する他の多くのソフトウェアも尊重するため、かなり面白い要件です:)また、この種の機能を簡単に追加できます。上記のコードに(space属性を確認し、その値が 'preserve'であるかどうかを確認しないでください。)

21
user797257

空白はXMLドキュメント内で重要です。インデントに空白を使用することは、実際には存在しない重要なデータを導入するため、XMLの不適切な使用法です。悲しいことに、これは標準です。空白を取り除くために採用するプログラムによるアプローチは、せいぜい推測にすぎません。データの一部を踏まずに、空白を適切に削除するには、XMLが何を伝達しているかについての知識が必要です。

7
Thanatos
xmlStr = xmlDocument.toprettyxml(indent='\t', newl='\n', encoding='UTF-8')
fix = re.compile(r'((?<=>)(\n[\t]*)(?=[^<\t]))|(?<=[^>\t])(\n[\t]*)(?=<)')
newXmlStr = re.sub(fix, '', xmlStr )

から このソース

1
cmelx

Xml.dom.minidomのtoprettyxml()について気になるのは、空白行が追加されることだけです。分割されたコンポーネントを取得していないようです。そのため、空白行を削除する簡単な関数を作成しました。

#!/usr/bin/env python

import xml.dom.minidom

# toprettyxml() without the blank lines
def prettyPrint(x):
    for line in x.toprettyxml().split('\n'):
        if not line.strip() == '':
            print line

xml_string = "<monty>\n<example>something</example>\n<python>parrot</python>\n</monty>"

# parse XML
x = xml.dom.minidom.parseString(xml_string)

# clean
prettyPrint(x)

そして、これはコードが出力するものです:

<?xml version="1.0" ?>
<monty>
        <example>something</example>
        <python>parrot</python>
</monty>

Toprettyxml()を単独で使用する場合、つまりprint(toprettyxml(x))を使用すると、不要な空白行が追加されます。

<?xml version="1.0" ?>
<monty>


        <example>something</example>


        <python>parrot</python>


</monty>
0
Steve Goossens