Ruslan Polupan
Ruslan PolupanСәуір 4, 2018, 2:54 Т.Ж.

Парсинг логов XML формата.

Qt, XML, логи, парсинг

Доброго времени суток.

Вопрос скорее теологического плана.
Возникла необходимость представить в читабельном виде логи обмена между сервисами.
Логи такого формата:
18.04.03 03:46:19.261 [GET_DISCOUNT] TransactionNo=4709 SCardNo=2551000547876 MPosCheckId=310731 GoodsCount=1 additionalAttributeList.Count=0
18.04.03 03:46:23.598 [THTTPProtocol.Post -> request] <?xml version="1.0" encoding="windows-1251"?>
<Data><Type>GET_DISCOUNT</Type><context><partnerID>10</partnerID><locationID>4001</locationID><terminalID>4001</terminalID><posID>1</posID><cashierID>17</cashierID><cashierFullName>Милованова Полина</cashierFullName><login>user1</login><password>user1</password><cardNo>2551000547876</cardNo><cardHash>7B0C042167106DF919222D4596451393</cardHash><transactionDate>2018-04-03 03:46:19</transactionDate></context><transactionNo>4709</transactionNo><transactionHash>E7EF9D3FC4154B7CB24D386487C96149</transactionHash><online>1</online><posReceipt>0</posReceipt><terminalReceipt>310731</terminalReceipt><GoodsList><goods><code1>3</code1><code2>3</code2><code3>1</code3><name>2710124194*Бенз.А-92</name><quantity>5.25</quantity><price>28.55</price><amount>149.89</amount><amountDiscount>0.00</amountDiscount><flagDiscount>0</flagDiscount><bonusMaxRedeem>149.88</bonusMaxRedeem></goods></GoodsList><PayType>1</PayType><totalAmount>149.89</totalAmount><totalAmountBeforeDiscount>149.89</totalAmountBeforeDiscount><additionalAttributeList/></Data>

18.04.03 03:46:23.598 [THTTPProtocol.Post <- answer] <?xml version="1.0" encoding="windows-1251"?><Data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><errorCode>0</errorCode><errorDescription>Нет ошибок</errorDescription><Messages><Message><Channel>1</Channel><MessageDescription>Общий баланс бонусов 31.84</MessageDescription></Message></Messages><bonusList><GoodsData><code1>0</code1><code2>3</code2><code3>1</code3><amount>149.89</amount><bonusIssuance>0</bonusIssuance><bonusRedeem>31.84</bonusRedeem><Discount>0</Discount><discountCode /><discountAmount>0.00</discountAmount><discountSource>0</discountSource><discountPercent>0</discountPercent></GoodsData></bonusList><clmTrnId>751008</clmTrnId><balanceActive>31.84</balanceActive><balanceTotal>31.84</balanceTotal></Data>
18.04.03 03:46:26.671 [ISSUANCE] TransactionNo=4710 SCardNo=2551000547876 MPosCheckId=310731 GoodsCount=1 additionalAttributeList.Count=0
18.04.03 03:46:33.207 [THTTPProtocol.Post -> request] <?xml version="1.0" encoding="windows-1251"?>
<Data><Type>ISSUANCE</Type><context><partnerID>10</partnerID><locationID>4001</locationID><terminalID>4001</terminalID><posID>1</posID><cashierID>17</cashierID><cashierFullName>Милованова Полина</cashierFullName><login>user1</login><password>user1</password><cardNo>2551000547876</cardNo><cardHash>7B0C042167106DF919222D4596451393</cardHash><transactionDate>2018-04-03 03:46:26</transactionDate></context><transactionNo>4710</transactionNo><transactionHash>2AA2BF06B710904EC2909E90C3A36F98</transactionHash><online>1</online><posReceipt>0</posReceipt><terminalReceipt>310731</terminalReceipt><GoodsList><goods><code1>3</code1><code2>3</code2><code3>1</code3><name>2710124194*Бенз.А-92</name><quantity>5.25</quantity><price>28.55</price><amount>149.89</amount><amountDiscount>0.00</amountDiscount><flagDiscount>0</flagDiscount><bonusMaxRedeem>149.88</bonusMaxRedeem></goods></GoodsList><PayType>1</PayType><totalAmount>149.89</totalAmount><totalAmountBeforeDiscount>149.89</totalAmountBeforeDiscount><additionalAttributeList/></Data>

18.04.03 03:46:33.207 [THTTPProtocol.Post <- answer] <?xml version="1.0" encoding="windows-1251"?><Data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Messages><Message><Channel>1</Channel><MessageDescription>Карта Glusco Club:</MessageDescription></Message><Message><Channel>1</Channel><MessageDescription>2551 0005 4787</MessageDescription></Message><Message><Channel>1</Channel><MessageDescription>Стан рахунку GlusCoin:</MessageDescription></Message><Message><Channel>1</Channel><MessageDescription>Нараховано:             1.5</MessageDescription></Message><Message><Channel>1</Channel><MessageDescription>Витрачено:                0</MessageDescription></Message><Message><Channel>1</Channel><MessageDescription>Баланс:               33.34</MessageDescription></Message></Messages><errorCode>0</errorCode><errorDescription>Нет ошибок</errorDescription><bonusList><GoodsData><code1>0</code1><code2>3</code2><code3>1</code3><amount>149.89</amount><bonusIssuance>1.5</bonusIssuance><bonusRedeem>0</bonusRedeem><Discount>0</Discount><discountAmount>0.00</discountAmount><discountPercent>0</discountPercent></GoodsData></bonusList><clmTrnId>751011</clmTrnId><TotalIssuance>1.5</TotalIssuance><TotalRedeem>0</TotalRedeem><balanceActive>33.34</balanceActive><balanceTotal>33.34</balanceTotal></Data>
Вопрос в том что не могу придумать какой инструментарий использовать для разбора их и соответсвенно для наглядного отображения с возможностью поиска данных.

Буду признателен за любой совет либо комментарий.
Спасибо.
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

6
Evgenii Legotckoi
  • Сәуір 4, 2018, 3:08 Т.Ж.
  • (өңделген)

Добрый день!

Qt обладает встроенными средствами парсинга XML формата.
При этом есть два вариант
  1. Использовать QXmlStreamWriter и QXmlStreamReader - это более низкоуровневый вариант. В большинстве случаев не требуется.
  2. Использовать QDomDocument - создаёт представление документа в виде Node дерева. Более высокоуровневый вариант. Несколько удобнее. Рекомендую использовать этот вариант.
Статьи с примерами
  1. Qt/C++ - Урок 011. XML файлы в Qt - чтение и запись - используются QXmlStreamWriter и QXmlStreamReader

  2. Qt/C++ - Урок 045. SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene - Используется QDomDocument

  3. Qt/C++ - Урок 072. Пример векторного редактора на Qt - там в исходниках есть куски кода с использованием QDomDocument.

Некоторые вопросы на форуме с использованием XML
    Ruslan Polupan
    • Сәуір 4, 2018, 8:27 Т.Ж.

    Спасибо.

    Но чего я напрочь заблудился в QDomDocument. Толковой статьи для чайников не нашел :-)
      Ruslan Polupan
      • Шілде 3, 2018, 6:55 Т.Ж.

      Снова вернулся к этой теме .

      Нашел такой вот пример.
      void MainWidget::on_pushButton_clicked()
      {
          //Очистка виджета иерархического списка (дерева)
          ui->treeWidget->clear();
      
          //Создание объекта чтения xml
          QXmlStreamReader xmlReader;
          //Создание стека элементов дерева
          //Верхний элемент стека - текущий родительский элемент
          QStack<QTreeWidgetItem*> itemStack;
      
          //Загрузка текста в объект чтения
          xmlReader.addData(ui->textBrowser->toPlainText());
      
          //Цикл до конца документа
          while (!xmlReader.atEnd()){
              //Случай открывающего тега
              if (xmlReader.isStartElement()){
                  //Получение имени открывающегося тега
                  QString str = xmlReader.name().toString();
                  //Получение объекта QStringList
                  QStringList sl = str.split(",");
                  //Создание нового элемента дерева
                  QTreeWidgetItem* item = new QTreeWidgetItem(sl);
                  //Если есть родительский элемент, добавляем новый элемент в качестве дочернего
                  if (itemStack.count()>0){
                      itemStack.top()->addChild(item);
                  }
                  //иначе добавляем в качестве корневого элемента
                  else {                
                      ui->treeWidget->addTopLevelItem(item);
                  }
                  //Открывающийся тег становится текущим родительским
                  itemStack.push(item);
      //            qDebug() << xmlReader.readElementText();
              }
              //Случай закрывающего тега
              if (xmlReader.isEndElement()){
      
                  //Если стек не пуст, поднимаемся вверх по иерархии
                  if (itemStack.count()>0)
                      itemStack.pop();
              }
              //Чтение следующей единицы документа
      
              xmlReader.readNext();
          }
          //Если в процессе разбора xml-документа возникла ошибка,
          //выводим её в консоль qDebug()
          if (xmlReader.hasError())
              qDebug() << xmlReader.errorString();
      }
      Структуру выводит то что надо.

      Но что-то никак не пойму как выводить значение тегов если они есть. т.е если это не ветка списка и у тега есть значение.



        Evgenii Legotckoi
        • Шілде 3, 2018, 4:24 Т.Қ.

        А Вы не могли бы скинуть код того тега и и описать, что подразумеваете под значением?

        А то у меня уже голова после рабочего дня не соображает.
          Ruslan Polupan
          • Шілде 4, 2018, 1:47 Т.Ж.

          Во вложении архив с проектом. XML в самом виджете.

            Evgenii Legotckoi
            • Шілде 4, 2018, 5:43 Т.Қ.

            Неудобство QXmlStreamReader заключается в том, что Вы должны знать структуру документа, из которого извлекаете данные. Поэтому нужно знать заранее все теги с которыми будете работать.


            При этом метод readElementText() сработает правильно в том случае, когда тег не содержит вложенных тегов.

            Как вариант, можете определить константное поле со списком тегов.

            class MainWidget : public QWidget
            {
                Q_OBJECT
            
            public:
                explicit MainWidget(QWidget *parent = 0);
                ~MainWidget();
            
            private slots:
                //Слот, автоматически связываемый по имени
                //с сигналом clicked() объекта кнопки pushButton
                void on_pushButton_clicked();
            private:
                Ui::MainWidget *ui;
            
                // Добавляем список тегов, из которых нужно извлечь данные
                const QStringList ELEMENTS_WITH_TEXT = {
                    "Type", "partnerID", "locationID", "terminalID", "posID"
                };
            };

            А вот вам исправленный цикл, который распарсит те данные, которые должны содержать только текст.
            //Цикл до конца документа
                while (!xmlReader.atEnd()) {
                    //Случай открывающего тега
                    if (xmlReader.isStartElement()){
                        //Получение имени открывающегося тега
                        QString str = xmlReader.name().toString();
            
                        //Получение объекта QStringList
                        if (ELEMENTS_WITH_TEXT.contains(str))
                        {
                            str = str.append(" " + xmlReader.readElementText());
                        }
            
                        //Создание нового элемента дерева
                        QTreeWidgetItem* item = new QTreeWidgetItem(QStringList() << str);
                        //Если есть родительский элемент, добавляем новый элемент в качестве дочернего
                        if (itemStack.count()>0){
                            itemStack.top()->addChild(item);
                        }
                        //иначе добавляем в качестве корневого элемента
                        else {                
                            ui->treeWidget->addTopLevelItem(item);
                        }
                        //Открывающийся тег становится текущим родительским
                        itemStack.push(item);
                    }
                    //Случай закрывающего тега
                    if (xmlReader.isEndElement()){
            
                        //Если стек не пуст, поднимаемся вверх по иерархии
                        if (itemStack.count()>0)
                            itemStack.pop();
                    }
                    //Чтение следующей единицы документа
            
                    xmlReader.readNext();
                }

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

              Пікірлер

              Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
              Кіріңіз немесе Тіркеліңіз
              AD

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Нәтиже:50ұпай,
              • Бағалау ұпайлары-4
              m
              • molni99
              • Қаз. 26, 2024, 1:37 Т.Ж.

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Нәтиже:80ұпай,
              • Бағалау ұпайлары4
              m
              • molni99
              • Қаз. 26, 2024, 1:29 Т.Ж.

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Нәтиже:20ұпай,
              • Бағалау ұпайлары-10
              Соңғы пікірлер
              ИМ
              Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
              Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
              Evgenii Legotckoi
              Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
              Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
              A
              ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
              Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
              Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas5Шілде 5, 2024, 11:02 Т.Ж.
              QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              Енді форумда талқылаңыз
              m
              moogoҚар. 22, 2024, 7:17 Т.Ж.
              Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
              Evgenii Legotckoi
              Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
              добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
              t
              tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
              google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
              NSProject
              NSProjectМаусым 4, 2022, 3:49 Т.Ж.
              Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

              Бізді әлеуметтік желілерде бақылаңыз