LINUX.ORG.RU

Найти границы XML-документа

 ,


0

1

Есть файл, в котором идут подряд несколько XML-документов. Какая существующая библиотека позволит из программы на C++ найти границы этих документов (для дальнейшего парсинга их)?

Пробовал скормить это QXmlStreamReader'у, но тот ругается ошибкой:

XML declaration not at start of document.

до того, как readNext() вернёт EndDocument.

ну да, любой XML парсер будет ругаться, если там много заголовков - это ненормально для XML формата. лучше делить чем-то другим, а потом уже скармливать отдельные порции парсерам.

делить файл на куски можно любым сишным поиском по строке <?xml version=«1.0»?>

Iron_Bug ★★★★★
()
Ответ на: комментарий от anonymous

И кодировка может присутствовать: encoding=«UTF-8» например.

anonymous
()

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

Если пытаться делить слитые документы до парсинга, можно попробовать искать начало документа по регекспу «^\<\?xml», если, конечно, такие заголовки там везде присутствуют.

blexey ★★★★★
()
Последнее исправление: blexey (всего исправлений: 1)
Ответ на: комментарий от intelfx

Нельзя парсить регэкспами. А разделить один файл на много xml-к вполне можно.

solovey ★★
()

Любой.

Породить свой поток от файла, который в начале породит <data><d1>, а на каждый следующий <?xml.*?> будет его заменять на </dN><dN+1> и в конце всё это закроет </dNlast></data>.

vtVitus ★★★★★
()
Ответ на: комментарий от intelfx

ОК, в каких ещё случаях, кроме ожидаемого, в его документе можно будет найти последовательность «<?xml» в самом начале строки?

blexey ★★★★★
()
Ответ на: комментарий от blexey

Можно разгребать и дерево, уже распарсенное любой доступной библиотекой.

Qt'шная парсилка не переваривает, когда несколько документов слиты вместе, она начинает ругаться на ошибку раньше, чем говорит мне о конце документа. Если бы она сначала сказала о конце документа, я бы мог отрезать на этом месте и запустить QXmlStreamReader заново уже с этого места. Есть какая-то библиотека, которая забьёт на повторяющиеся «<?xml» и построит дерево (лес?), несмотря на несколько корневых элементов?

Если пытаться делить слитые документы до парсинга, можно попробовать искать начало документа по регекспу «^\<\?xml», если, конечно, такие заголовки там везде присутствуют.

Хотелось бы не привязываться к таким вещам, заголовок может быть не везде, а ещё текст «<?xml» может быть внутри CDATA, как уже сказали выше. Поэтому я ищу скорее что-то вроде pull-парсера, но который умеет начинать новый документ, как только встретил конец предыдущего в потоке данных (вряд ли есть хорошо работающий способ разделить xml'ки, не парся их).

gentoo_root ★★★★★
() автор топика

Наверняка у тебя какой-то частный случай. Какая-то программа сплошняком генерит хмл документы в 1 файл. Народ правильно советует, найди шаблон, как эти документы заканчиваются/начинаются. Подели поток стандартными средствами и парси куски. Но лучше перенастрой верхний уровень, который тебе такую лажу выдает.

hardsky
()
Ответ на: комментарий от gentoo_root

Встречный вопрос:
Кому стрельнуло в голову сливать несколько нормальных XML документов на кучу так, чтобы потом, героически преодолевая искусственные трудности, делить их обратно, придумывая универсальные велосипеды?

blexey ★★★★★
()
Ответ на: комментарий от intelfx

Сваливание нескольких XML документов в один файл - это отступление от стандарта XML. Поэтому корректного решения в пределах стандарта XML искать нет смысла.

blexey ★★★★★
()
Ответ на: комментарий от blexey

А кто говорит про «в пределах стандарта»? Меня попросили показать пример, на котором регэксповый парсер сфейлится =)

intelfx ★★★★★
()

Можно попытаться, например, взять tinyxml, который толерантен к нескольким root node в документе, и его похачить (т. е. заставить выводить позицию окончания каждого следующего root node). Но он не парсит DTD.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
#include <QDebug>
#include <QFile>
#include <QXmlStreamReader>

void parseMultiRoot(QString fname)
{
    QFile f(fname);
    if(f.open(QFile::ReadOnly)==false)
        return;
    QByteArray data = f.readAll();
    QXmlStreamReader *xml = new QXmlStreamReader();
    qDebug()<<"new QXmlStreamReader()";

    QList<QByteArray> list = data.split('<');
    if(list.at(0)=="") list.takeFirst();
    while(list.isEmpty()==false) {
        data = list.takeFirst();
        if(list.isEmpty()==false) data.prepend("<");
        xml->addData(data);
        while(!xml->atEnd())
        {
            xml->readNext();
            qDebug()<<xml->tokenString()<<xml->text();
            if(xml->tokenType()==QXmlStreamReader::EndDocument) {
                qDebug()<<"new QXmlStreamReader()";
                delete xml;
                xml = new QXmlStreamReader();
                break;
            }
        }
        if(xml->hasError())
            qDebug()<<xml->errorString();
        qDebug()<<xml->lineNumber();
    }
}
anonymous
()
Ответ на: комментарий от blexey

Кому стрельнуло в голову сливать несколько нормальных XML документов на кучу так, чтобы потом, героически преодолевая искусственные трудности, делить их обратно, придумывая универсальные велосипеды?

Я знаю, что так неправильно делать, даже в моём случае есть выход лучше. В принципе, наверное, поэтому и нет библиотеки, которая заточена под этот случай.

gentoo_root ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Вот это интересный workaround, так действительно QXmlStreamReader выдаст сначала EndDocument, а не ошибку, как было у меня. Вот только время его работы будет значительно хуже, чем могло бы быть, потому что придётся каждый раз заново проходить по тексту и парсить, добавляя небольшие кусочки.

gentoo_root ★★★★★
() автор топика
Ответ на: комментарий от gentoo_root

Еще вариант - воспользоваться ограничениями стандарта XML:

Поскольку данным стандартом не разрешается использовать последовательность «]]>» внутри CDATA, значит последовательность «]]>]]>» никогда не должна встретиться в валидном XML документе.

Значит её вполне можно использовать для разделения XML документов за их пределами внутри одного файла.

blexey ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.