На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
  
> Парсинг xml
    Всем доброго времени суток, есть такой xml файл:
    ExpandedWrap disabled
      <order>  
       <object>  
       <name >John Doe</name>
       <cost>5000</cost>    
       </object>  
       <object>  
       <name>Tom Hall</name>  
       <cost>5000</cost>
       </object>
       </order>

    Необходимо распарсить имена, моя наработка:
    ExpandedWrap disabled
              size_t found = str.find("<name"); //в переменной str хранится весь xml файл
              string aux = str.substr(found);
              found = aux.find(">");
              aux = aux.substr(found + 1);
              size_t end_found = aux.find("</name");
              string find_str = aux.substr(0, end_found);

    Но так получаю лишь одно имя, как бы зациклить дабы получить все?
      Цитата skinex @
      еобходимо распарсить имена, моя наработка:

              size_t found = str.find("<name"); //в переменной str хранится весь xml файл
              string aux = str.substr(found);


      У тебя каждый раз копируется остаток строки, работать будет очень медленно.

      Надо что-то типа
      ExpandedWrap disabled
        size_t pos = 0;
        for (;;)
        {
            pos = str.find('<', pos);
            if (pos == std::string::npos)
                break;
         
                size_t pos2 = ++pos
         
            ...............
         
            pos = str.find('>', pos);
            if (pos == std::string::npos)
                !!!!error;
            
                std::string name(str, pos, pos2 - pos);
                pos2 = ++pos;
            .................
         
            pos = str.find('<', pos);
            if (pos == std::string::npos)
                !!!!error;
         
                if (str[pos + 1] != '/')
                    //Рекурсивно парсим вложенные теги, меняем значения pos, pos2
                else
                {
                     std::string value(str, pos, pos2 - pos);
                     pos2 = (pos += 2);
                }
         
                .................................
                pos = str.find('>', pos);
                .................................
        }


      Пример очень грубый и нерабочий, но принцип в целом, надеюсь, должен быть понятен
        1. MSXML
        2. TinyXml git
        3. PugiXml
        4. RapidXml
        5. Xerces

        Если этого вам не достаточно и вы настаиваете на велосипеде, обращаю внимание на метод find у ваших строк. У него есть второй аргумент, если вы будете его использовать, ваша идея с зацикливанием действительно осуществима.

        Опередили :D
        Сообщение отредактировано: VisualProg -
          Использовать парсеры не вариант. Знаю про второй параметр find, пробовал его использовать:
          ExpandedWrap disabled
             while (myt < string::npos) {
                    if (myt == string::npos)
                        break;
                    size_t found = myXml.find("<name", myt);
                    string aux = myXml.substr(found);
                    found = aux.find(">");
                    aux = aux.substr(found + 1);
                    size_t end_found = aux.find("</name");
                    cout << end_found << endl;
                    string find_str = aux.substr(0, end_found);
                    myt += found + find_str.length() + end_found+4;
                }

          Но получаю довольно много выводов....
            Цитата skinex @
            Но получаю довольно много выводов....

            Используйте второй аргумент как курсор. Он должен всё время перемещаться вправо. В вашем примере, он не двигается с места.

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

            ExpandedWrap disabled
              #include <iostream>
              #include <string>
               
              void parse(std::string xml, std::string tag){
               
                  size_t pos1 = 0;
                  size_t pos2 = 0;
                  
                  std::string OPEN_TAG  = "<"+tag+">";
                  std::string CLOSE_TAG = "</"+tag+">";
                  
                  for(;;){
                  
                      pos1 = xml.find(OPEN_TAG,pos1);
                      if(pos1 == std::string::npos){
                          break;
                      }
                      pos1+=OPEN_TAG.length();
                      
                      pos2 = xml.find(CLOSE_TAG,pos1);
                      if(pos2 == std::string::npos){
                          std::cout<<"Закрывающий тег '"+tag+"' отсутствует!\n";
                          exit(-1);
                      }
                      
                      std::string value = xml.substr(pos1,pos2-pos1);
                      std::cout<<value<<"\n";
                      pos1 = pos2;
                      
                  }
               
              }
               
              int main() {
                  std::string xml = "<order><object><name>John Doe</name><cost>5000</cost></object><object><name>Tom Hall</name><cost>5000</cost></object></order>";
                  std::cout<<"start...\n";
                  parse(xml,"name");
                  return 0;
              }


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

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

            В общем, вот вариант с атрибутами:

            ExpandedWrap disabled
              #include <iostream>
              #include <string>
                  
              void parse(std::string xml, std::string tag){
               
                  size_t pos1 = 0;
                  size_t pos2 = 0;
               
                  std::string OPEN_TAG  = "<"+tag;
                  std::string CLOSE_TAG = "</"+tag+">";
               
                  for(;;){
               
                      pos1 = xml.find(OPEN_TAG,pos1);
                      if(pos1 == std::string::npos){
                          break;
                      }
                      pos1+=OPEN_TAG.length();
               
                      pos1 = xml.find(">",pos1);
                      if(pos1 == std::string::npos){
                          std::cout<<"Закрывающая скобка тега '"+tag+"' отсутствует!\n";
                          exit(-2);
                      }
                      pos1++;
               
                      pos2 = xml.find(CLOSE_TAG,pos1);
                      if(pos2 == std::string::npos){
                          std::cout<<"Закрывающий тег '"+tag+"' отсутствует!\n";
                          exit(-1);
                      }
               
                      std::string value = xml.substr(pos1,pos2-pos1);
                      std::cout<<value<<"\n";
                      pos1 = pos2;
               
                  }
               
              }
               
              int main() {
                  std::string xml = "<order><object><name>John Doe</name><cost>5000</cost></object><object><name>Tom Hall</name><cost>5000</cost></object></order>";
                  std::cout<<"start...\n";
                  parse(xml,"name");
                  return 0;
              }
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:


            Рейтинг@Mail.ru
            [ Script execution time: 0,0276 ]   [ 17 queries used ]   [ Generated: 28.03.24, 22:05 GMT ]