【问题标题】:How to read XML header in Python如何在 Python 中读取 XML 标头
【发布时间】: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,但找不到任何相关内容)。

【问题讨论】:

    标签: python xml python-3.x xml-parsing


    【解决方案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 相比。
    猜你喜欢
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 1970-01-01
    • 2016-04-29
    • 2017-06-28
    • 2018-04-10
    • 2018-05-16
    相关资源
    最近更新 更多