Intruder
IntruderҚаз. 4, 2019, 7: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
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

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

7
Intruder
  • Қаз. 4, 2019, 7:52 Т.Ж.
  • (өңделген)

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

</tag1>
    Evgenii Legotckoi
    • Қаз. 4, 2019, 8:47 Т.Ж.

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

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

    <body>
    <h1>Heading</h1>
    <p>Hello <b>you</b></p>
    </body>
    
      Intruder
      • Қаз. 4, 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, 2019, 1: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, 2019, 3:18 Т.Қ.

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

            Intruder
            • Қаз. 9, 2019, 6:52 Т.Ж.

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

              Evgenii Legotckoi
              • Қаз. 9, 2019, 3: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. Я сам об этом не знал. Сейчас только попробовал, поэкспериментировал и догадался, как это дело работает.

                Пікірлер

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

                C++ - Тест 001. Первая программа и типы данных

                • Нәтиже:66ұпай,
                • Бағалау ұпайлары-1
                t

                C++ - Тест 001. Первая программа и типы данных

                • Нәтиже:33ұпай,
                • Бағалау ұпайлары-10
                t

                Qt - Тест 001. Сигналы и слоты

                • Нәтиже:52ұпай,
                • Бағалау ұпайлары-4
                Соңғы пікірлер
                G
                GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
                Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
                d
                dblas5Шілде 5, 2024, 11:02 Т.Ж.
                QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                k
                kmssrАқп. 8, 2024, 6:43 Т.Қ.
                Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                АК
                Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
                Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                Енді форумда талқылаңыз
                Evgenii Legotckoi
                Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                F
                FynjyШілде 22, 2024, 4:15 Т.Ж.
                при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
                BlinCT
                BlinCTМаусым 25, 2024, 1 Т.Ж.
                Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
                BlinCT
                BlinCTМамыр 5, 2024, 5:46 Т.Ж.
                Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                Evgenii Legotckoi
                Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
                Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

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