如何在 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 中读取数据

如何在c#中的xml之后添加数据并在之后读取xml?

如何在 python 中读取具有特定标签属性的 xml?

如何在 Tomcat web.xml 中添加标头?

如何在 Flask 中捕获和读取传入 HTTP 请求的标头? [复制]

如何以角度读取 Http 响应标头