Intruder
Intruder4. Oktober 2019 07:36

XML парсинг сложного тега <tag1> text part 1 <tag2> text </tag2> text part 2 </tag1>

Всем доброго времени суток.
Например есть вот такой тег:

<tag1> any text part 1 <tag2> text </tag2> any text part 2 </tag1>

Как реализовать корректное чтение и запись такой конструкции в объектную модель и модель QDom? С таким тегом сталкиваюсь впервые, поэтому не совсем понятно как действовать в такой ситуации.

Всем спасибо за помощь в решении даннго о вопроса.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

7
Intruder
  • 4. Oktober 2019 07:52
  • (bearbeitet)

Я там описался, закрывающий последний тег - это

</tag1>
    Evgenii Legotckoi
    • 4. Oktober 2019 08:47

    Добрый день.
    А какой хотите получить итоговый результат? В том же QDomNode есть метод QDomNode::childNodes(), который возвратит список все вложенных тегов.

    То есть как раз для подобных случаев

    <body>
    <h1>Heading</h1>
    <p>Hello <b>you</b></p>
    </body>
    
      Intruder
      • 4. Oktober 2019 10:18

      Евгений, задача у меня следующая:
      1. Есть файл XML.
      2. Есть объектная модель, которая соответствует файлу XML.
      Мне нужно прорпарсить xml файл и записать значения в объектную модель.
      Я написал следующий код, примерный:

      #include <iostream>
      #include <QtXml/QDomDocument>
      #include <QFile>
      #include <QTextStream>
      
      int main()
      {
          QDomDocument doc;
          doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
          QDomElement element = doc.createElement("element");
          element.appendChild(doc.createTextNode("TEXT 1"));
          QDomElement element1 = doc.createElement("element1");
          element1.appendChild(doc.createTextNode("text1"));
          element.appendChild(element1);
          element.appendChild(doc.createTextNode("TEXT 2"));
          doc.appendChild(element);
          QFile file("C:/TEMP/test.xml");
          if(file.open(QIODevice::WriteOnly)){
              QTextStream out(&file);
              out.setCodec("UTF-8");
              out << doc.toString();
              file.close();
          }
          std::cout << "start import" << std::endl;
      
          QDomDocument doc1;
      
          if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
          {
              std::cout << "File not exist";
              return -1;
          }
          if(!doc1.setContent(&file)){
              file.close();
              return -1;
          }
          file.close();
              QDomNode node = doc1.firstChild();
                  while (!node.isNull()) {
                      QDomElement el1 = node.toElement();
                      std::cout << el1.tagName().toStdString() + el1.text().toStdString();
                      if(el1.hasChildNodes()){
                          QDomNode node1 = el1.firstChild();
                          while (!node1.isNull()) {
                              QDomElement el2 = node1.toElement();
                              std::cout << el2.tagName().toStdString() + " " + el2.text().toStdString() << std::endl;
                              node1 = node1.nextSibling();
                          }
                      }
                      node = node.nextSibling();
                  }
          return 0;
      }
      

      Так вот после создания файла XML получаю вот такое содержимое файла:

      <?xml version="1.0" encoding="UTF-8"?>
      <element>TEXT 1<element1>text1</element1>TEXT 2</element>
      


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

        Evgenii Legotckoi
        • 6. Oktober 2019 13:41

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

        Что-нибудь вроде такого

        class TreeItem
        {
        public:
            TreeItem(TreeItem* parent = nullptr)
            {
                if (parent)
                {
                    parent->addChild(this);
                }
            }
        
            void addChild(TreeItem* child)
            {
                m_children.push_back(child);
            }
        
        private:
            TreeItem* m_parent;
            std::vector<TreeItem*> m_children;
        }
        

        QDomDocument - это тоже дерево. Поэтому при прохождении тегов можно составить своё собственное дерево. Но нужно понимать конечную цель.

          Intruder
          • 6. Oktober 2019 15:18

          Евгений, я думаю, что тут нужно будет разбирать строку. Дерево из QDomElement я построить могу - это не является какой-то сложной задачей. Задача не тривиальная потому, что если текст разбит на части внутри одного тега и эти части могут быть обернуты в дргуие теги, то, если взять значение головного тега, то он вернет строку целиком, т.е. захватит и текст других тегов. Вот в чем задача. Как разобрать строку и вернуть ее обратно именно в той последовательности, которая присутвует в файле. Есть наметки, но нужно проверить.

            Intruder
            • 9. Oktober 2019 06:52

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

              Evgenii Legotckoi
              • 9. Oktober 2019 15:45

              Добрый день.

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

              #include <iostream>
              #include <QtXml/QDomDocument>
              #include <QFile>
              #include <QTextStream>
              #include <QDebug>
              
              int main()
              {
                  QDomDocument doc;
                  doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));
                  QDomElement element = doc.createElement("element");
                  element.appendChild(doc.createTextNode("TEXT 1"));
                  QDomElement element1 = doc.createElement("element1");
                  element1.appendChild(doc.createTextNode("text1"));
                  element.appendChild(element1);
                  element.appendChild(doc.createTextNode("TEXT 2"));
                  doc.appendChild(element);
                  QFile file("/home/dekadent/test.xml");
                  if(file.open(QIODevice::WriteOnly)){
                      QTextStream out(&file);
                      out.setCodec("UTF-8");
                      out << doc.toString();
                      file.close();
                  }
                  std::cout << "start import" << std::endl;
              
                  QDomDocument doc1;
              
                  if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
                  {
                      std::cout << "File not exist";
                      return -1;
                  }
                  if(!doc1.setContent(&file)){
                      file.close();
                      return -1;
                  }
              
                  file.close();
                  QDomNode node = doc1.firstChild();
              
                  while (!node.isNull()) {
                      QDomElement el1 = node.toElement();
                      std::cout << el1.tagName().toStdString() << " " << el1.text().toStdString() << std::endl;
                      if(el1.hasChildNodes()){
                          std::cout << "size of child nodes " << el1.childNodes().size() << std::endl;
                          for (int i = 0; i < el1.childNodes().size(); ++i)
                          {
                              std::cout << i << std::endl;
                              QDomNode node2 = el1.childNodes().item(i);
                              if (node2.isText())
                              {
                                  // Это текстовая нода, нужна иная обработка.
                                  std::cout << node2.toText().data().toStdString();
                              }
                              QDomElement el2 =  node2.toElement();
                              std::cout << el2.tagName().toStdString() << " " << el2.text().toStdString() << std::endl;
                          }
                      }
                      node = node.nextSibling();
                  }
                  return 0;
              }
              
              

              Весь прикол в том, что метод nextSibling() , который вы использовали, не работает на текстовые ноды, то есть на QDomText. Я сам об этом не знал. Сейчас только попробовал, поэкспериментировал и догадался, как это дело работает.

                Kommentare

                Nur autorisierte Benutzer können Kommentare posten.
                Bitte Anmelden oder Registrieren
                Letzte Kommentare
                A
                ALO1ZE19. Oktober 2024 15:19
                Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                ИМ
                Игорь Максимов5. Oktober 2024 14:51
                Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                d
                dblas55. Juli 2024 18:02
                QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                k
                kmssr9. Februar 2024 02: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 10:27
                добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
                JW
                Jhon Wick1. Oktober 2024 22: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 16:09
                Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
                F
                Fynjy22. Juli 2024 11:15
                при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                Folgen Sie uns in sozialen Netzwerken