如何在 Python 中读取 XML 标头
Posted
技术标签:
【中文标题】如何在 Python 中读取 XML 标头【英文标题】:How to read XML header in Python 【发布时间】:2018-08-03 02:34:31 【问题描述】:如何在 Python 3 中读取 XML 文档的标题?
理想情况下,我会使用 defusedxml 模块作为documentation states that it's safer,但在这一点上(经过数小时的尝试后),我会满足于任何解析器。
例如,我有一个看起来像这样的文档(这实际上来自一个练习):
<?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>
我想知道如何访问根节点之前的所有内容。
这似乎是一个笼统的问题,我以为我很容易在网上找到答案,但我想我错了。我找到的最接近的东西是this question on Stack Overflow,它并没有真正帮助(我查看了xml.sax,但找不到任何相关内容)。
【问题讨论】:
【参考方案1】:试试这个代码! 我假设变量 's' 中的临时 xml。
我声明了一个 MyParser 类,它具有 XmlDecl 的功能来打印 XML 标头,第二个函数的目的是解析 XML 标头。所以首先使用 xml.parsers 中定义的 ParserCreate() 函数创建解析器.
现在创建 MyParser 类 'parser' 的对象并使用对象引用调用 parse 函数。
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)
【讨论】:
谢谢,但请参阅相关说明。另外,我发现很难遵循您的代码;也许一些 cmets 或简化会有所帮助。 是的,当然!我稍后会更新上面的描述@Ratler 这实际上并没有帮助。而且它仍然没有在根节点之前获得完整的标头。【参考方案2】:我尝试了minidom
,根据您提供的link,它很容易受到十亿次笑声和二次爆炸攻击。这是我的代码:
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'>
您可以使用defusedxml
中的minidom
。我下载了那个包,只是用 from defusedxml.minidom import parse
替换了 import 并且代码使用相同的输出。
【讨论】:
太棒了!这正是我一直在寻找的。第三个选项(childNodes[0])似乎是获取所有标题的最通用的选项。 我很高兴能帮上忙 :-)【参考方案3】:使用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 相比。以上是关于如何在 Python 中读取 XML 标头的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有标头信息的 Python 2.7-Pandas 中读取数据