Стандартная библиотека языка Python уже содержит готовый XML анализатор (парсер). Доступ к нему осуществляется через пакет xml.
1 |
import xml.dom.minidom |
1 |
from xml.dom import minidom |
Загрузка из файла:
1 |
dom = xml.dom.minidom.parse("filename.xml") |
1 |
dom = xml.dom.minidom.parseString(xmlStr) |
1 |
dom.normalize() |
1 2 3 4 5 6 |
TestNode 1234567890 TestItem1 TestItem2 TestItem3 |
Данный пример уже использовался для разбора XML в Delphi. Сегодня же мы будем выполнять его анализ средствами Python.
Загрузим XML документ.
1 2 3 |
import xml.dom.minidom dom = xml.dom.minidom.parse("test.xml"); dom.normalize() |
Разбор простого узла
Для поиска узлов по названию тега служит метод getElementsByTagName(tagName). Этот метод возвращает список тегов с именем указанным в качестве параметра. Если тег с таким именем только один, можно сразу обратиться к нему по индексу 0.
1 |
node1=dom.getElementsByTagName("node1")[0] |
1 |
print("name="+node1.nodeName |
1 |
print("attr="+node1.getAttribute("attr")) |
1 |
print("attr="+node1.attributes.item(0).value) |
1 |
print("value="+node1.childNodes[0].nodeValue) |
Разбор сложного узла на примере массива
Узел, обозначенный тегом array, содержит настоящий массив элементов. Однако его разбор не представляет особой сложности. Сначала получаем нужный дочерний узел через коллекцию childNodes или метод getElementsByTagName и работаем с ним как с простым узлом.
В качестве примера рассмотрим обход дочерних узлов в цикле.
1 2 3 4 5 |
nodeArray=dom.getElementsByTagName("array")[0] childList=nodeArray.childNodes for child in childList: print(child.nodeName) print(child.childNodes[0].nodeValue) |
Если какой-либо из дочерних узлов не является простым, работаем с ним как с обычным сложным узлом. Находим нужный дочерний узел и т.д. Но, что делать, когда сложный узел содержит ещё и значения?
Например.
1 2 3 4 |
12 TestItem1 TestItem2 TestItem3 |
Распознаются несколько типов узлов, но основных из них три.
- DOCUMENT_NODE – документ;
- ELEMENT_NODE – элемент. Обычный узел;
- TEXT_NODE – текст. Этот тип узла соответствует значению тега.
Выполним разбор приведённого выше сложного узла с учётом данных замечаний.
1 2 3 4 5 6 7 8 |
nodeArray=dom.getElementsByTagName("array")[0] childList=nodeArray.childNodes for child in childList: if child.nodeType==child.TEXT_NODE: print(child.nodeValue) else: print(child.nodeName) print(child.childNodes[0].nodeValue) |
Сравнение со стандартными парсерами некоторых других языков
Стандартный XML парсер Python не отличается удобством и значительно уступает по своим возможностям другим парсерам даже для самого Python (тому же lxml). При этом, главным недостатком как в отношении удобства так и функционала является, конечно, отсутствие возможности работать с XML иначе как средствами DOM в сочетании с явно недостаточно продуманной объектной моделью и, как следствие, неоправданно громоздким инструментарием.
Для сравнения. TXMLDocument в Delphi также работает только с DOM, но разбор структуры документа с его помощью гораздо проще и удобнее во многом благодаря отсутствию необходимости создавать в коде сложные конструкции наподобие тех, что разработчик вынужден использовать в Python.
Что касается работы с XML в .NET Framework, то здесь нет смысла даже сравнивать. LINQ to XML, поддержка XPath «из коробки» … К счастью, в Iron Python всё это доступно.
Конечно, возможностей стандартного парсера вполне достаточно для решения задач практически любой степени сложности. Только каковы издержки реализации на его основе?..
Большое спасибо! Долго думал как начать работать с XML потоками Сейчас вроде бы разобрался