如何在Python中解析表示xml.dom.minidom节点的字符串?
我有一堆用xml.dom.minidom创建的节点对象,这些节点是xml.dom.Node类型的。我把它们(一个一个地)存储在数据库里,方法是用节点对象的toxml()方法把它们转换成字符串。
问题是,有时候我想把这些字符串再转换回合适的节点对象,但我发现Python自带的各种库使用的是Expat,而Expat无法解析像''这样的字符串,或者任何不是正确的XML字符串的内容。
所以,有没有人有什么好主意?我知道我可以用某种方式把节点序列化(也就是“打包”),然后再反序列化(“解包”),但这样感觉不太好,我更希望能以一种我能读懂的形式存储,以便于维护。难道没有什么方法可以做到这一点吗?
针对有人怀疑这是否可能,我给个例子说明一下:
>>> import xml.dom.minidom
>>> x=xml.dom.minidom.parseString('<a>foo<b>thing</b></a>')
>>> x.documentElement.childNodes[0]
<DOM Text node "u'foo'">
>>> x.documentElement.childNodes[0].toxml()
u'foo'
>>> xml.dom.minidom.parseString(x.documentElement.childNodes[0].toxml())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xml/dom/minidom.py", line 1928, in parseString
return expatbuilder.parseString(string)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xml/dom/expatbuilder.py", line 940, in parseString
return builder.parseString(string)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xml/dom/expatbuilder.py", line 223, in parseString
parser.Parse(string, True)
xml.parsers.expat.ExpatError: syntax error: line 1, column 0
换句话说,".toxml()"方法生成的东西并不能被Expat(因此也不能被parseString)解析。
我想要的是一种能把u'foo'解析成文本节点的东西。也就是说,能逆转.toxml()效果的东西。
3 个回答
你可以试着用 <![CDATA[xxx]]>
来包裹你的内容。
在你的代码中,你可以在解析之前加上这个标签。
'<![CDATA[<a>foo<b>thing</b></a>]]>'
from xml.dom.minidom import parseString
try:
node = parseString('')
except Exception:
node = None
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。
你需要存储哪些类型的节点呢?
显然,元素节点如果用 .toxml('utf-8')
进行序列化,应该可以正常工作;结果应该可以直接作为 XML 文档解析,并且可以通过 documentElement
获取到这个元素,只要里面没有需要在文档类型中定义的实体引用。
另一方面,文本节点则需要进行 HTML 解码或者一些包装才能解析。如果你只需要元素和文本节点,可以通过第一个字符来判断它是否是元素,因为元素的第一个字符必须是 <
:
var xml= node.toxml('utf-8')
...
if (xml.startswith('<')):
node= minidom.parseString(xml).documentElement
else:
node= minidom.parseString('<x>%s</x>'%xml).documentElement.firstChild
注释节点也可以通过检查 <!--
来存储。
其他类型的节点,比如属性(Attr),就比较麻烦,因为它们的 XML 表示和文本节点不容易区分。你可能需要存储一个额外的 nodeType
值来记住它。不过,另一方面,minidom 对属性并没有实现 toxml()
,所以这也许不是个问题。