Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.05.2019, 07:11   #1
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
Вопрос Парсинг регуляркой RegExpr, запутался

Вобщем имеется кусок XML странички, в котором есть два "блока" с данными (блок <items> и блок <profiles>). Мне нужно используя регулярку RegExpr спарсить все данные из тега <video>, то есть данные тега <from_id> и тега <date> и одновременно все данные из тега <user>, то есть данные тега <photo> и тега <name>. При этом во втором блоке данные идут вперемешку, но есть зацепка - одинаковые ID в тегах <from_id> и <id>. Т.е к одному ID идут должны одновременно спарситься теги <date>, <photo> и <name> за один проход цикла.


Код:
<response>
<items list="true">
<video>
<from_id>123</from_id>
<date>1559177700</date> 
</video>
<video>
<from_id>456</from_id>
<date>1559177701</date> 
</video>
<video>
<from_id>789</from_id>
<date>1559177702</date> 
</video>
</items>
------------------------------------------------
<profiles list="true">
<user>
<id>789</id>
<photo>https://албалбалб.com/</photo>
<name>Иван</name>
</user>
<user>
<id>123</id>
<photo>https://блаблабла.com/</photo>
<name>Анастасия</name>
</user>
<user>
<id>456</id>
<photo>https://балбалбал.com/</photo>
<name>Андрей</name>
</user>
</profiles>
</response>
FleXik вне форума Ответить с цитированием
Старый 30.05.2019, 08:04   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от FleXik Посмотреть сообщение
Мне нужно используя регулярку RegExpr спарсить все данные из тега <video>
не нужно, возьмите XML парсер.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 31.05.2019, 05:21   #3
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
не нужно, возьмите XML парсер.
можно пожалуйста пример реализации в виде кода или хотя-бы в текстовом виде как совместить два блока, учитывая одинаковый ID?
FleXik вне форума Ответить с цитированием
Старый 31.05.2019, 21:32   #4
JoLan
Delphi XE7
Пользователь
 
Аватар для JoLan
 
Регистрация: 26.07.2010
Сообщений: 74
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
не нужно, возьмите XML парсер.
Цитата:
Сообщение от FleXik Посмотреть сообщение
можно пожалуйста пример реализации в виде кода или хотя-бы в текстовом виде как совместить два блока, учитывая одинаковый ID?
Очень рекомендую использовать XML.VerySimple: https://github.com/Dennis1000/verysimplexml

Его достаточно добавить в настройках library path вашей IDE и затем просто подключать в uses:
Код:
uses
//...
XML.VerySimple;
demo_thread_329191.png

Для написания кода использовал Delphi XE7. В этом коде нет проверок на существование узлов, их можно дописать самому. Неполный листинг для демонстрации компонента (полный проект во вложении):

Код:
TForm1 = class(TForm)
private
  FProfiles:  TArray<TProfileInfo>;
  procedure   FParseFile(Filename: String);
end;

//...

procedure TForm1.FParseFile(Filename: String);
var xml: TXMLVerySimple;
    profiles, videos: TXMLNodeList;
    profile_node, video_node: TXMLNode;
    last_profile_index: Integer;
    str_id: String;
begin
  xml := TXMLVerySimple.Create;
  xml.LoadFromFile(Filename);

  //создавать объект списка узлов не требуется,
  //так как метод FindNodes автоматически инициализирует экземпляр списка,
  //а вот освободить память нужно
  profiles := XML.ChildNodes.Find('response').Find('profiles').FindNodes('user');
  videos := XML.ChildNodes.Find('response').Find('items').FindNodes('video');

  last_profile_index := 0;
  SetLength(Self.FProfiles, profiles.Count);

  //перебираем все профили
  for profile_node in profiles do
  begin
    //Запоминаем айди пользователя, чтобы каждый раз не вызывать Find
    str_id := profile_node.Find('id').Text;

    //парсим текущий узел XML в нашу структуру
    Self.FProfiles[last_profile_index].Parse(profile_node);

    //Ищем в списке видео все записи, которые соответствуют айди пользователя
    for video_node in videos do
      if (video_node.Find('from_id').Text = str_id) then
        //И парсим этот узел в текущего пользователя
        Self.FProfiles[last_profile_index].AddVideo(video_node);

    Inc(last_profile_index);
  end;

  //Убираемся за собой
  profiles.Free;
  videos.Free;
  str_id := '';
  xml.Free;
end;
Код:
  TVideoInfo = record
    PostDate:   Integer;
    //При необходимости можно дополнить структуру и метод парсинга
    procedure   Parse(XMLNode: TXMLNode);
  end;

  TProfileInfo = record
    ID:         Integer;
    Photo:      String;
    Name:       String;
    Videos:     TArray<TVideoInfo>;
    //При необходимости можно дополнить структуру и метод парсинга
    procedure   Parse(XMLNode: TXMLNode);
    procedure   AddVideo(XMLNode: TXMLNode);
    procedure   Clear;
  end;

//...

procedure TVideoInfo.Parse(XMLNode: TXMLNode);
begin
  Self.PostDate := XMLNode.Find('date').Text.ToInteger();
end;

//...

procedure TProfileInfo.Parse(XMLNode: TXMLNode);
begin
  Self.ID := XMLNode.Find('id').Text.ToInteger();
  Self.Photo := XMLNode.Find('photo').Text;
  Self.Name := XMLNode.Find('name').Text;
end;

procedure TProfileInfo.AddVideo(XMLNode: TXMLNode);
var vCount: Integer;
begin
  vCount := Length(Self.Videos);
  SetLength(Self.Videos, vCount + 1);
  Self.Videos[vCount].Parse(XMLNode);
end;

procedure TProfileInfo.Clear;
begin
  Self.Photo := '';
  Self.Name := '';
  Self.Videos := [];
end;
Вложения
Тип файла: 7z code_thread_329191.7z (2.2 Кб, 10 просмотров)
JoLan вне форума Ответить с цитированием
Старый 31.05.2019, 21:50   #5
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от JoLan Посмотреть сообщение
Его достаточно добавить в настройках library path вашей IDE
не надо так делать, потом же после переустановки ОС или Дельфи не вспомните что куда добавлять.
Лучше положить библиотеки в папку проекта (например в папку lib) или рядом с ней, и в современных версиях Дельфи вроде в настройках проекта (которые в dproj сохраняются) есть про пути, там указать относительные пути (lib\verysimplexml).
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 01.06.2019, 02:42   #6
JoLan
Delphi XE7
Пользователь
 
Аватар для JoLan
 
Регистрация: 26.07.2010
Сообщений: 74
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
не надо так делать, потом же после переустановки ОС или Дельфи не вспомните что куда добавлять.
Лучше положить библиотеки в папку проекта (например в папку lib) или рядом с ней, и в современных версиях Дельфи вроде в настройках проекта (которые в dproj сохраняются) есть про пути, там указать относительные пути (lib\verysimplexml).
Для меня удобней настроить IDE, чтобы потом всегда иметь доступ к любым библиотекам в любом проекте.

Если каждый раз при создании нового проекта его нужно настраивать и копировать все нужные файлы, - то это будет занимать какое-то время. Хорошо, если есть память и необходимо скопировать всего пару pas-файлов. Но такой подход неприменим к случаю, когда необходимо подключить десяток-другой компонент.
JoLan вне форума Ответить с цитированием
Старый 01.06.2019, 09:57   #7
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Обычно новые проекты (особенно требующие кучи библиотек) не так часто создаются.
И можно ж всегда скопировать настройки из старого.

Кроме переустановки своей ОС/Дельфи естественно другая важная причина — не получится легко передать проект другому человеку, ему тоже придется отдельно качать все либы, добавлять пути и т.д. + при совместной работе может получиться, что у вас будут разные версии какой-то либы, кто-то забудет передать какую-то либу и т.д.

Вообще в нормальных современных ЯП эти проблемы решаются менеджером зависимостей: npm, Composer, NuGet, Maven, pip и т.д.
Цитата:
Сообщение от JoLan Посмотреть сообщение
необходимо скопировать всего пару pas-файлов
причем тут количество, у меня в примере все сторонние либы были в папке lib.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 01.06.2019 в 10:26.
Alex11223 вне форума Ответить с цитированием
Старый 01.06.2019, 15:56   #8
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
По умолчанию

Когда я переустанавливаю - папка lib как бы тоже уничтожается... Смысл всё в ней держать?
ResourceSpace вне форума Ответить с цитированием
Старый 01.06.2019, 16:00   #9
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Нет, она в папке проекта.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 03.06.2019, 03:18   #10
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

JoLan, спасибо большое за код и потраченное время

может кто поделится примером парсинга на XMLDocument?
FleXik вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
RegExpr, парсинг данных до тех пор пока есть что парсить FleXik Общие вопросы Delphi 2 16.03.2015 13:41
Проблема с регуляркой RegExpr FleXik Общие вопросы Delphi 7 17.11.2013 17:22
проблема с регуляркой helldog PHP 7 24.02.2012 13:21
проблема с регуляркой designer999 Общие вопросы Delphi 1 10.12.2010 00:37