Как я могу прочитать заголовок документа XML в Python 3?

В идеале, я бы использовал модуль 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>

Мне интересно, как получить доступ ко всему до корневого узла.

Это кажется таким общим вопросом, что я думал, что легко найду ответ в Интернете, но, думаю, я ошибся. Самым близким, что я нашел, был этот вопрос о переполнении стека что не очень помогло (я заглянул в xml.sax , но не смог найти ничего актуального).

6
Ratler 23 Фев 2018 в 07:16

3 ответа

Лучший ответ

Я попробовал 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'>

Вы можете использовать minidom из defusedxml. Я скачал этот пакет и просто заменил импорт на from defusedxml.minidom import parse, и код работал с тем же выводом.

4
qwermike 23 Фев 2018 в 19:19

Попробуйте этот код! Я предполагаю временный xml в переменной 's'.

Я объявляю класс MyParser, имеющий функцию XmlDecl для печати заголовка XML, и цель второй функции - проанализировать заголовок XML. Поэтому сначала создайте анализатор с помощью функции ParserCreate (), определенной в xml.parsers.

Теперь создайте объект класса 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)
0
Usman 23 Фев 2018 в 05:35

С 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">
3
mzjn 23 Фев 2018 в 16:46