Поиск по блогу

среда, 27 августа 2008 г.

Парсинг XML на Delphi

Начнем с самого простого — с синтаксического анализа документа формата XML. Этот документ имеет четкую структуру и как нельзя лучше подходит для начала изучения парсинга. Еще один приятный момент — для парсинга XML нам пока даже не пригодится умение составлять регулярные выражения (это не значит, что их не надо знать :) ).

XML — формат для хранения структурированных данных. Если вы лишь краем уха слышали про этот формат, но близко не сталкивались, прочитайте скучную, но полезную статью об XML на Wiki.

Итак, прочитали? Проверим, понимаем ли мы друг друга. Вот скрин ссылки http://newyorg.myminicity.com/xml, как ее видит Firefox (вставляю рисунком, так как блоггер что-то не очень любит подобного рода код).


City — корневой элемент. Элементы: host, name, region, ranking и т.д.. Атрибуты: code (у элемента region, значение атрибута — "RU"), com, env, ind, sec, tra (атрибуты элемента bases, каждый атрибут имеет числовое значение). Обратите внимание, что bases — пустой элемент. Сходится с теорией?

Рассмотрим стандартный компонент Delphi, позволяющий работать с XML. Это TXMLDocument с вкладки Internet, с которой нам в будущем придется еще поработать.



Компонент можно положить на форму, а можно создавать динамически по мере надобности.

Итак, создаем форму, помещаем на нее компонент и 5 компонентов TEdit. В первый мы запишем содержимое элемента population, в 4 остальных — значения атрибутов ind, tra, sec, env. Все это делается чрезвычайно просто. В обработчике нажатия кнопки, например, пишем:


XMLDocument1.LoadFromFile('http://newyorg.myminicity.com/xml');
XMLDocument1.Active := true;
Edit1.Text := XMLDocument1.DocumentElement.ChildNodes['population'].Text;
Edit2.Text := VarToStr(XMLDocument1.DocumentElement.ChildNodes['bases'].Attributes['ind']);
Edit3.Text := VarToStr(XMLDocument1.DocumentElement.ChildNodes['bases'].Attributes['tra']);
Edit4.Text := VarToStr(XMLDocument1.DocumentElement.ChildNodes['bases'].Attributes['sec']);
Edit5.Text := VarToStr(XMLDocument1.DocumentElement.ChildNodes['bases'].Attributes['env']);
XMLDocument1.Active := false;

Подведем итоги.

Чтение атрибута узла можно произвести так:
Root.GetAttribute(WideString('NodeName'));
(где Root — элемент)

Так работать можно, естественно, не только с корневым элементом, но и с его дочерними узлами:
Root.ChildNodes.Nodes[i].GetAttribute(WideString('NodeName'));

Запись атрибута:
Root.SetAttribute(WideString('NodeName'),'NodeValue');

Количество дочерних узлов определяем:
Root.ChildNodes.Count;

Вот и все. Мы получили все, что хотели, плюс начальные навыки работы с компонентом TXMLDocument.

Статьи схожей тематики:



17 комментариев:

  1. Не используйте, plz, названия компонентов, которые ставит Delphi.

    ОтветитьУдалить
  2. Это же не реальный проект, а тестовая форма... я ее сделала специально для этого поста) Тут вроде все элементарно и интуитивно понятно...

    ОтветитьУдалить
  3. Вот еще полезная ссылка по работе с XML в Delphi: http://www.codenet.ru/progr/delphi/stat/Using-XML/

    ОтветитьУдалить
  4. S1700075_MP1701

    0114076
    50.00
    04.02.2010
    026345
    9264





    как мне прочитать то что в packet?

    ОтветитьУдалить
  5. Kest, в комментариях xml не проходит.

    Базовых операций для работы с xml в delphi - по пальцам пересчитать. Вы хоть что-либо пробовали, прежде чем задать вопрос? Ведь наверняка это элементарно, и можно найти решение самостоятельно.

    ОтветитьУдалить
  6. <?xml version="1.0" encoding='UTF-8'?>
    <data>
    <element>
    1
    </element>
    <element>
    2
    </element>
    </data>

    А если вот так? как вычленить 2 элемент по имени?

    Edit1.Text := XMLDocument1.DocumentElement.ChildNodes['element'].Text;

    засада блин(

    ОтветитьУдалить
  7. А не подойдет просто так?
    Edit1.Text := XMLDocument1.DocumentElement. ChildNodes.Nodes[1].Text;

    Если обязательно "второй с определенным именем", то у всех вершин проверять имя и считать те, которые с требуемым именем.

    ОтветитьУдалить
  8. я не знаю заранее сколько их будет, этих элементов. Был бы еще параметр, позволяющий тащить "однофамильца" по номеру было бы все шоколадно...

    Ладно, буду обходить траблы дедовскими методами -
    хитрость помноженная на лень и годящаяся только в моей конкретной ситуации))

    PS не ожидал увидеть ответ так быстро, восхищен, сражен на месте))
    хороший ресурс, пишите еще

    ОтветитьУдалить
  9. Большое спасибо, уже не первый раз статьи в блоге выручают =)

    ОтветитьУдалить
  10. В этом случае все понятно - Edit2.Text := VarToStr(XMLDocument1.DocumentElement.ChildNodes['bases'].Attributes['ind']);
    А как быть например в случае если нужны данные из - 17?

    ОтветитьУдалить
  11. Анонимный, похоже, blogger скушал ваш код )) Не понимаю, что за 17...

    ОтветитьУдалить
  12. Я уже и не надеялся найти такое простое и доходчивое описание работы с XML документом. Чаще попадались странички с длинным описанием - что такое XML, с чем его едят, пьют и т.д. И почти ничего не сказано о том как работать с этим форматом! А я не программист и никогда на него не учился... Спасибо, Маша!

    ОтветитьУдалить
  13. Приятно, что статья оказалась полезной :)

    ОтветитьУдалить
  14. Спасибо за статью, очень помогло!

    ОтветитьУдалить
  15. Спасибо, второй день мучаюсь с XML.
    После вашей статьи всё получилось.)
    Единственная проблема с кодировкой.
    У меня в одном из атрибутов русские буквы, и Delphi не хочет с ними работать. Пишет: "Тест" is not a valid component name. Может подскажете что-нибудь по-этому поводу?

    ОтветитьУдалить
  16. Не понятно что такое "узел"

    ОтветитьУдалить
  17. уже при 500 элементов чувствуется затык

    ОтветитьУдалить

Комментарии модерируются, вопросы не по теме удаляются, троллинг тоже.

К сожалению, у меня нет столько свободного времени, чтобы отвечать на все частные вопросы, так что, может, свой вопрос лучше задать на каком-нибудь форуме?

Поделиться