如何在Python中读取XML头

7

如何在Python 3中读取XML文档的头部?

理想情况下,我会使用defusedxml模块,因为文档说明它更安全, 但是在这一点上(经过数小时的尝试后),我会接受任何解析器。

例如,我有一个文档(实际上是来自一个练习),看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <!-- this is root -->
    <!-- CONTENTS -->
</plist>

我想知道如何访问根节点之前的所有内容。
这似乎是一个非常普遍的问题,我以为我可以在网上轻松找到答案,但我错了。我找到的最接近的东西是Stack Overflow上的这个问题, 它并没有真正帮助我(我研究了xml.sax,但找不到任何相关的内容)。
3个回答

5

我尝试了minidom,根据您提供的链接,它容易受到亿万笑话和二次扩张攻击的影响。以下是我的代码:

from xml.dom.minidom import parse

dom = parse('file.xml')
print('<?xml version="{}" encoding="{}"?>'.format(dom.version, dom.encoding))
print(dom.doctype.toxml())
#or
print(dom.getElementsByTagName('plist')[0].previousSibling.toxml())
#or
print(dom.childNodes[0].toxml())

输出:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist  PUBLIC '-//Apple Computer//DTD PLIST 1.0//EN'  'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
<!DOCTYPE plist  PUBLIC '-//Apple Computer//DTD PLIST 1.0//EN'  'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
<!DOCTYPE plist  PUBLIC '-//Apple Computer//DTD PLIST 1.0//EN'  'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>

你可以使用来自 defusedxmlminidom。我下载了这个包,只需用 from defusedxml.minidom import parse 替换导入语句,代码就能以相同的输出运行。

太棒了!这正是我在寻找的。第三个选项(childNodes [0])似乎是获取所有标题最通用的方法。 - Ratler
我很高兴能够帮助 :-) - qwermike

5
使用 lxml 库,您可以通过 DocInfo 对象访问文档属性。
from lxml import etree

tree = etree.parse('input.xml')
info = tree.docinfo
v, e, d = info.xml_version, info.encoding, info.doctype

print('<?xml version="{}" encoding="{}"?>'.format(v, e))
print(d)

输出:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

谢谢!这个完美地解决了问题,但我接受了@mike-kaskun的答案,因为(a) defusedxml和(b) minidom似乎是默认包(至少在我的系统上),而lxml则需要安装。 - Ratler

0
尝试这段代码! 我假设变量's'中是临时xml。 我声明一个名为MyParser的类,其中包含一个XmlDecl函数用于打印XML头和第二个函数的目的是解析XML头。因此,首先使用xml.parsers中定义的ParserCreate()函数创建解析器。 现在创建MyParser类的对象“parser”并使用对象引用调用解析函数。
from xml.parsers import expat

s = """<?xml version='1.0' encoding='iso-8859-1'?>
       <book>
           <title>Title</title>
           <chapter>Chapter 1</chapter>
       </book>"""

class MyParser(object):
    def XmlDecl(self, version, encoding, standalone):
        print ("XmlDecl", version, encoding, standalone)

    def Parse(self, data):
        Parser = expat.ParserCreate()
        Parser.XmlDeclHandler = self.XmlDecl
        Parser.Parse(data, 1)

parser = MyParser()
parser.Parse(s)

谢谢您,但请看一下问题的澄清。另外,我发现很难跟着您的代码;也许加入一些注释或简化会有帮助。 - Ratler
是的,当然!我稍后会更新上面的描述 @Ratler - Usman
实际上,那并没有帮助。而且仍然无法获取根节点之前的完整标头。 - Ratler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接