如何在Python中解析表示xml.dom.minidom节点的字符串?

5 投票
3 回答
19034 浏览
提问于 2025-04-15 23:02

我有一堆用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 个回答

0

你可以试着用 <![CDATA[xxx]]> 来包裹你的内容。

在你的代码中,你可以在解析之前加上这个标签。

'<![CDATA[<a>foo<b>thing</b></a>]]>'
6
from xml.dom.minidom import parseString

try:
  node = parseString('') 
except Exception:
  node = None

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

5

你需要存储哪些类型的节点呢?

显然,元素节点如果用 .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(),所以这也许不是个问题。

撰写回答