LINUX.ORG.RU

Qt:: парсинг .xml

 


0

1

Всем привет!

Такая вот простая незадача: есть до умопомрачения простейшая xml, но не могу найти внятного пояснения в стандартных Qt библиотек для этого случая


<тэг1>
   Текст 1.
   <тэг2>
	Текст 4.
   </тэг2>
   Текст 2.
   <тэг3>
	Текст 5.
   </тэг3>
   Текст 3.
</тэг1>

Суть в том, что сначала надо прочитать тэг1 с текст1, текст2, текст3, потом, соответственно, тэг2 с текст4 и тэг3 с текст5. QXmlStreamReader явно не подходит, хотя и пробовал нагородить с запоминанием пройденный тэгов. Теперь мучаю QDomNode, но он ведет себя так же, как предыдущий: либо читает только текст находящийся в самом верху(текст1, текст4 и текст5), либо методом text() выдает все тексты внутри каждого тэга (т.е, для тэг1 выдает все тексты в порядке 1,4,2,5,3 и т.д.). Подскажите, кто знает, пожалуйста, как этого добиться, желательно, примером

код:

void MyClass::parse_xml(QDomNode &node)
{
    QDomNode domNode = node.firstChild();
    while (!domNode.isNull())
    {
        qDebug() << "el";
        if(domNode.isElement())
        {
            QDomElement domElement = domNode.toElement();
            if (!domElement.isNull())
            {
                qDebug() << "tagname: " << domElement.tagName();
                if (domElement.hasAttributes())
                {                    
                    QDomNamedNodeMap attrmap = domElement.attributes();
                    for (int i = 0; i < attrmap.count(); i++)
                    {
                        qDebug() << "attribute: " <<  attrmap.item(i).toAttr().name()
                                 << ", value:" << attrmap.item(i).toAttr().value();
                    }
                }
                qDebug() << "tagbody: " << domElement.text().simplified();
            }
        }        
        parse_xml(domNode);
        domNode = domNode.nextSibling();
    }
}


сначала надо прочитать тэг1 с текст1, текст2, текст3

XML не так устроен.

Но если сильно хочется - берём QDomDocument, и затем бегаем по QDomNode::childNodes().

RazrFalcon ★★★★★
()

до умопомрачения простейшая xml

Которую стОит предварительно провалидировать соответстующим XSD, иначе, если тебе подадут херь, то программа твоя сломается.

не могу найти внятного пояснения в стандартных Qt

Потому, что сам не понимаешь что творишь.

сначала надо прочитать тэг1 с текст1, текст2, текст3, потом, соответственно, тэг2 с текст4 и тэг3 с текст5

Что это за страшная бздня и кто придумал такую структуру хранения данных? Гнать ссаными тряпками!

мучаю QDomNode

Который нужно мучать уже после валидации, будучи уверенным, что структура DOM верна и все ожидаемые узлы в ней присутствуют.

код

Лапша из говна, пытающаяся валидировать безструктурную бздню.

Подскажите, кто знает, желательно, примером

Вот на основе полученных выше пинков, переосмысли задачу и попробуй написать код сам.

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

бегаем по QDomNode::childNodes()

Где нет никакой гарантии, что, в потоке между тегами-элементами будет всегда одна текстовая нода, там может быть и несколько (пробелы, переводы строк, отдельные слова).

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

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

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

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

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

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

не знаете

Знаю, потому, что делал.

С пробелами и переводами строк я справляюсь

С такой структурой данных — нет. Когда напорешься — вспомнишь мои слова.

кусок задачи, в которой имеется затык

Затык, не в задаче. И об этом не только я тебе сказал (XML не так устроен). Задача сама рассосется, если решить проблему в правильном месте.

а не проект века

А ты любитель хоп хоп и в продакшн?

не надо говорить, что такое решение не имеет смысла

Повторю: XML не так устроен.

оно просто может быть, и не спрашивать вашего разрешения

Кто-то и посреди красной площади туалет устроить может.

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

https://stackoverflow.com/questions/30500827/xml-indent-and-newline-for-new-c...

http://xmlsoft.org/FAQ.html

In XML all characters in the content of the document are significant including blanks and formatting line breaks.

The extra nodes you are wondering about are just that, text nodes with the formatting spaces which are part of the document but that people tend to forget. There is a function xmlKeepBlanksDefault () to remove those at parse time, but that's an heuristic, and its use should be limited to cases where you are certain there is no mixed-content in the document.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Так пустые строки могут содержать и пробелы и табы. Нельзя просто так взять и испортить данные. Неверно прочитав мы покажем не то, что было на самом деле, а неверно перезаписав — испортим в конец без возможности восстановить.

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

Да. Под пустыми я подразумевал whitespaces. Поэтому в кавычках.

PS: У меня есть самописный xml парсер, ибо нормальных не нашёл, поэтому немного в теме.

RazrFalcon ★★★★★
()

Может тебе стоит вместо while сделать if, а

parse_xml(domNode)
заменить на
parse_xml(domNode.nextSibling()) 

spock74
()

Меня выше отписавшиеся регистранты закидают ссаными тряпками, но https://pastebin.com/UzX1Yzzi
Вывод:

"тэг1"
"\n    Текст 1.\n    "
"\n    Текст 2.\n    "
"\n    Текст 3.\n"
"тэг2"
"\n        Текст 4.\n    "
"тэг3"
"\n        Текст 5.\n    "

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

Спасибо, товарищ 😊👍 ссаные тряпки беру на себя)

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

Я же тогда говорил что libxml2 справляется со всем. Да, там инопланетный интерфейс (по началу). Ну и ладно, раз свой, так свой. Не осуждаю. Возможно, если бы я делал похожую либу, то и задумался бы о написании своего, но т.к. не было схожих задач — пользовал готовое.

ox55ff прям наколенное решение синтетической задачки с хакатона. Зачем приучаешь к плохому? Не делай так больше.

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

libxml2 слишком жирный для моих задач. Ну и с распространением морока.

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

Ну вот для моих задач нужен. Хотя бы минимальная поддержка ENTITY. Поэтому и пришлось писать свой велосипед.

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

Я тоже. Только если нужно.

Нужно будет ради забава потестить.

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

Да, на средних файлах (300КБ) в 10 раз быстрее. Солидно. Но учитывая какой он примитивный - не удивительно. Он даже namespaces не поддерживает. И CDATA не обрабатывает.

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

Дык подсмотри в его сорцы, может там какое ноу-хау есть, которое к себе упереть сможешь, что даст прирост. А вдруг?

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

А что там валидировать? Парсер же тупо по токенам едет, а если что, то останавливается и говорит линию и символ.

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

Например, что символы подпадают под ограничения xml (https://www.w3.org/TR/xml/#NT-Char). То есть я проверяю, что tagname содержит только допустимые символы и прочее.

Ну и моя либа всего 3 KLOC, а pugi - 10KLOC. Правда у меня на кошерном расте, а не на плюсах.

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

я проверяю, что tagname содержит только допустимые символы и прочее

Можно ссылку с якорем на конкретное место в сорцах?

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

Перешел к fn is_xml_name*

match *self as u32

Не шарю в расте. Это чар который всегда 4 байта? Это конвертится в рантайме или *self уже и есть u32? Если нет, и там утф-8 с переменной длиной, то, возможно, получится ускорить, т.к. без конвертации в u32.

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

Да, всегда 4 байта. Сложно объяснить как оно работает, но да, в итоге utf-8 итерируется по utf-32: https://doc.rust-lang.org/src/core/str/mod.rs.html#502

Как оно будет работать без конвертации в uft-32 - без понятия, ибо по спеке XML я должен проверять utf-32.

RazrFalcon ★★★★★
()

У меня сомнения в том, что этот XML валиден

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

по спеке XML я должен проверять utf-32

Пишут что кроме утф-8 парсер обязан кушать и утф-16. Ладно, я так глубоко там не лазил. И что, вот прям вынь да полож, внутри утф-32 хотят?

Как оно будет работать без конвертации в uft-32 - без понятия

По первому байту уже понятно аскии это или нет. Вот полный набор условий на длину символа в байтах для утф-8:

if (firstByte < 128) {
    moreLen = 0;
} else if (firstByte < 224) {
    moreLen = 1;
} else if (firstByte < 240) {
    moreLen = 2;
} else if (firstByte < 248) {
    moreLen = 3;
} else if (firstByte < 252) {
    moreLen = 4;
} else {
    moreLen = 5;
}
Но, учитывая что я прочитал, что парсер обязан кушать и утф-16, то, действительно, для внутреннего представления требуется текст уже преобразованный в утф-32, чтобы не мудрить с условиями кодировок при валидации. Но если твой парсер умеет только утф-8 — можешь попробовать работать на основе условий что я скинул выше, как для валидации, так и для скачков позиции в потоке символов.

deep-purple ★★★★★
()
Ответ на: комментарий от RazrFalcon

Да я не настаиваю. Как руки дойдут — вспомни о чем говорили.

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