Ruslan Polupan
Ruslan Polupan4. April 2018 02: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
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

6
Evgenii Legotckoi
  • 4. April 2018 03:08
  • (bearbeitet)

Добрый день!

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. April 2018 08:27

    Спасибо.

    Но чего я напрочь заблудился в QDomDocument. Толковой статьи для чайников не нашел :-)
      Ruslan Polupan
      • 3. Juli 2018 06: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. Juli 2018 16:24

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

        А то у меня уже голова после рабочего дня не соображает.
          Ruslan Polupan
          • 4. Juli 2018 01:47

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

            Evgenii Legotckoi
            • 4. Juli 2018 17: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 в плане неизвестной структуры документа будет адекватнее себя вести, там можно проверить, имеются ли дочерние теги или нет.

              Kommentare

              Nur autorisierte Benutzer können Kommentare posten.
              Bitte Anmelden oder Registrieren
              Letzte Kommentare
              A
              ALO1ZE19. Oktober 2024 08:19
              Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь Максимов5. Oktober 2024 07:51
              Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas55. Juli 2024 11:02
              QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              k
              kmssr8. Februar 2024 18:43
              Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
              Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
              Jetzt im Forum diskutieren
              J
              JacobFib17. Oktober 2024 03:27
              добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
              JW
              Jhon Wick1. Oktober 2024 15:52
              Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
              КГ
              Кирилл Гусарев27. September 2024 09:09
              Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
              F
              Fynjy22. Juli 2024 04:15
              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

              Folgen Sie uns in sozialen Netzwerken