2010-07-22 153 views
17

如何刪除Python 2.6中XML字符串中的空格和換行符?我嘗試了以下軟件包:刪除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 

我不能使用Python 2.7,其將提供method參數。

minidom命名:一樣的:

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

這可能有助於使用LXML刪除從文本節點http://stackoverflow.com所有空行和空白頻段/ a/19396130/973699 – DevC 2013-10-16 06:09:42

回答

29

最簡單的解決辦法可能是使用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來確定哪些空白節點是重要的。

除此之外,你將不得不編寫自己的代碼刪除你不想要的空白(迭代後裔,並在適當情況下,設置僅包含空白來None或空字符串.text.tail屬性)

+0

我發現,正如@Steven指出的那樣,僅包含空格的元素沒有被清理。在調用'etree.tostring'後我使用了一個正則表達式:'re.sub(r'> \ s + <', '><',xml_str)' – Rodrigue 2012-06-12 14:08:42

+0

請替換'etree.XML(xml_str,parser = p)'在第一個片段中使用'etree.XML(xml_str,parser = parser)'。 – 2016-12-28 11:19:37

-3
xmlStr = ' '.join(xmlStr.split())) 

這使得所有文本在一個符合單個空格替代多個空格。

xmlStr = ''.join(xmlStr.split())) 

這將徹底刪除空間,包括裏面的文字空間,不能使用

第一種形式可以用的風險下使用(但是,您的要求),你給輸入:

xmlStr = '''<root> 
    <head></head> 
    <content></content> 
</root>''' 
xmlStr = ' '.join(xmlStr.split()) 
print xmlStr 
""" Output: 
<root> <head></head> <content></content> </root> 
""" 

這將是有效的XML。它可能需要通過某種xml檢查器檢查。你是否確實想要XML?您是否閱讀過文章: Python Is Not Java

+0

-1你的建議會像''「」 \ t \ tfoo「」「' – 2010-07-22 20:08:35

+0

這樣的東西被垃圾處理,我將不得不同意約翰。這根本不保留XML語法。 – mattbasta 2010-07-22 22:25:13

6

空白在XML文檔中很重要。使用空白進行縮進是XML的一種不好的用法,因爲它引入了實際上沒有的重要數據 - 可悲的是,這是常態。任何用於刪除空格的程序化方法最多隻能是一個猜測 - 您需要更好地瞭解XML如何傳遞以正確刪除空白,而不踩任何數據的腳趾。

-1

有點笨拙的解決方案沒有LXML :-)

data = """<root> 

    <head></head> <content></content> 

</root>""" 

data3 = [] 
data2 = data.split('\n') 
for x in data2: 
    y = x.strip() 
    if y: data3.append(y) 
data4 = ''.join(data3) 
data5 = data4.replace(" ","").replace("> <","><") 

print data5 

Output: <root><head></head><content></content></root> 
-1

如果空白在「非葉」節點就是我們正在嘗試刪除,然後下面的函數將做到這一點(遞歸如果指定):

from xml.dom import Node 

def stripNode(node, recurse=False): 
    nodesToRemove = [] 
    nodeToBeStripped = False 

    for childNode in node.childNodes: 
     # list empty text nodes (to remove if any should be) 
     if (childNode.nodeType == Node.TEXT_NODE and childNode.nodeValue.strip() == ""): 
      nodesToRemove.append(childNode) 

     # only remove empty text nodes if not a leaf node (i.e. a child element exists) 
     if childNode.nodeType == Node.ELEMENT_NODE: 
      nodeToBeStripped = True 

    # remove flagged text nodes 
    if nodeToBeStripped: 
     for childNode in nodesToRemove: 
      node.removeChild(childNode) 

    # recurse if specified 
    if recurse: 
     for childNode in node.childNodes: 
      stripNode(childNode, True) 

但是,Thanatos是正確的。空格可以用XML表示數據,因此請謹慎使用。

17

這裏的東西很快,我想出了,因爲我不想使用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屬性,不recure如果它的值是「保留」。)

+1

感謝您的支持 - 我不想將lxml添加到我的項目中,這完全符合我的需求。 – 2013-10-08 21:36:21

+2

太棒了。多謝,夥計。 – 2014-02-20 13:36:17

0
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) 

this source

0

困擾我大約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 ()本身,即打印(toprettyxml(X)),它增加了不必要的空行:

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


     <example>something</example> 


     <python>parrot</python> 


</monty>