Лучший способ анализировать XMPP-подобные потоки XML?

Я работаю над серверным приложением, которое получает данные через сокет TCP в XMPP-подобном формате XML, т.е. каждый дочерний элемент элемента <root> по существу представляет собой один отдельный запрос (раздел). Соединение закрывается, как только получено </root>. Я знаю, что должен каким-то образом использовать анализатор потоков, такой как SAX. Хотя для удобства я бы предпочел иметь древовидный интерфейс для доступа к дочерним элементам каждой строфы. (Данные, отправляемые с каждым запросом, невелики, поэтому я думаю, что имеет смысл читать каждую строфу целиком.)

Как лучше всего реализовать это в Python (желательно v3)?

Это код, в который я хотел бы его встроить. Не стесняйтесь указать мне совершенно другое направление для решения этой проблемы.

import socketserver
import settings

class MyServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

class MyRequestHandler(socketserver.StreamRequestHandler):
    def handle(self):
        pass

if __name__ == '__main__':
    server = MyServer((settings.host, settings.port), MyRequestHandler)
    server.serve_forever()

person balu    schedule 30.04.2010    source источник


Ответы (2)


Вы захотите использовать синтаксический анализатор на основе push, который генерирует события SAX. По сути, вам нужен синтаксический анализатор, который вы можете вызвать pushChunk(data) с частичным битом данных, и иметь обработчик событий для события дочернего конечного тега первого уровня, который генерирует ваши строфы. Затем его можно отправить в логику обработки приложения.

Если вы хотите увидеть пример этого, вот анализатор expat для libstrophe, клиентской библиотеки XMPP, которую я написал: http://github.com/metajack/libstrophe/blob/master/src/parser_expat.c

Создание целого документа для каждой строфы довольно дорого. Это можно реализовать с помощью одного экземпляра синтаксического анализатора, в отличие от постоянного создания новых синтаксических анализаторов документов для каждой строфы.

Если вам нужна работающая версия Python, вы, вероятно, можете использовать или вытащить код из Twisted Words (twisted.words.xish, я думаю).

person metajack    schedule 30.04.2010
comment
Другой прием заключается в использовании указателя одного элемента в качестве стека для вашей текущей позиции. Когда вы получаете событие нового элемента, вы создаете элемент в своем доме. Если стек не нулевой, вы добавляете этот элемент как дочерний к элементу стека и устанавливаете указатель стека на новый элемент. Когда вы получаете событие конечного элемента, вы устанавливаете указатель стека на родителя текущего указателя стека. Если указатель стека в конце этой операции равен нулю, у вас есть строфа. Примечание: это то, что код Джека, связанный с приведенным выше, более или менее делает. - person Joe Hildebrand; 05.05.2010
comment
На всякий случай, если кому-то понадобится решение Python для этого: stackoverflow.com/questions/1459648/ (сообщение помечено как принятый ответ). - person balu; 20.05.2010
comment
@JoeHildebrand Как бы вы получили нулевой указатель стека? Поток xmpp xml начинается с <stream:stream> и не закрывается до момента отключения; вы никогда не закончите свою строфу, так как никогда не дойдете до конца своего элемента. Возможно, уточните, что вы имеете в виду под стеком; это стек объектов XmlDomElement? (Самое худшее в XMPP — это необходимость заново изобретать полный анализатор XML с нуля...) - person Ian Boyd; 03.11.2019
comment
Да, стек элементов DOM. Это должно быть относительно специфичным для XMPP, поскольку вы отслеживаете состояние документа при запуске и гарантируете, что ни один из разделов не является дочерним элементом потока: корень потока. - person Joe Hildebrand; 04.11.2019

Что мы сделали для Skates, так это то, что мы использовали синтаксический анализатор Sax для построения потока, но использовали этот синтаксический анализатор для построения целый документ для каждой полученной строфы.

person Julien Genestoux    schedule 30.04.2010