Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

Вы сейчас или в ближайшем обозримом будущем планируете разрабатывать кроссплатформенное приложение с использованием Firemonkey?



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 5 марта 2010 в 18:56.
Категории: Delphi в Web.


Казалось бы, такая мелочь - удалить из узла IXMLNode пустой аттрибут xmlns, а нервов потратил :) . Что в принципе нам предоставляет в распоряжение Delphi для работы с XML? Могу перечислить только то, с чем я работал - это модули xmldoc, xmldom, xmlIntf, msxml...вроде бы из стандартных все модули. Можно ещё долго перечислять сторонние компоненты и модули типа simpleXML и т.д., но мне необходимо было реализовать задуманное только с использованием модулей входящих в состав Delphi по умолчанию. А задача была довольно простая - отправить запрос, содержащий определенный XML-документ, на сервер (Googl'у) и создать новый Календарь. То есть, воспользоваться возможностями API Google Celendar.


Формат документа - проще некуда:

<entry xmlns='http://www.w3.org/2005/Atom'
       xmlns:gd='http://schemas.google.com/g/2005'
       xmlns:gCal='http://schemas.google.com/gCal/2005'>
  <title type='text'>Little League Schedule</title>
  <summary type='text'>This calendar contains the practice schedule and game times.</summary>
  <gCal:timezone value='America/Los_Angeles'></gCal:timezone>
  <gCal:hidden value='false'></gCal:hidden>
  <gCal:color value='#2952A3'></gCal:color>
  <gd:where rel='' label='' valueString='Oakland'></gd:where>
</entry>

Создать такой документ - дело пяти минут. Единственный момент, который следовало учесть - это объявить пространства имен (xmlns) в корневом узле, иначе Google не принимает такой документ и возникает ошибка.  В своей работе я чаще всего использую для работы с XML интерфейс IXMLDocument. В этот раз решил поступить также. Вот как выглядел код в самом начале:

var ADoc: IXMLDocument;
Root,Node:IXMLNode;
[...]
ADoc:=NewXMLDocument;
ADoc.Active:=true;
Root:=ADoc.AddChild('entry');
for I:=0 to High(clNameSpaces) do //добавляем xmlns
Root.DeclareNamespace(clNameSpaces[i,0],clNameSpaces[i,1]);
 
Node:=Root.AddChild('title'); //добавили узел
Node.Attributes['type']:='text';//добавили аттрибут
Node.Text:='Test Celendar'; //добавили текстовое содержимое
[...]

Аналогичным образом добавлялись и узлы gCal:. В итоге получаяем вот такой документ:

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005" xmlns:gCal="http://schemas.google.com/gCal/2005">
 <title xmlns="" type="text">TestCelendar</title>
 <summary xmlns="" type="text">Основной календарь</summary>
 <gCal:timezone value="Asia/Omsk"/>
 <gCal:hidden value="false"/>
 <gCal:color value="#5229A3"/>
 <gd:where valueString="Славный город Омск"/>
</entry>

Обратите внимание на пустые атрибуты xmlns у двух первых узлов. Отправляя такой документ Googl'у получаем ошибку "Добавляемый календарь не имеет названия", т.е. как раз узла title.

Если убираем из корневого элемента:

xmlns="http://www.w3.org/2005/Atom"

То узлы title и summary записываются нормально, но опять же Гугл посылает такой документ в печь. Чтобы кто-то из Вас, уважаемые читатели, не совершал теже самые "танцы с бубном" при работе с XML (всё-таки этот пост я пишу больше для новичков в еле работы с XML) я перечислю то, что делать бесполезно. Итак, при использовании IXMLDocument Вы не избавитесь от пустых атрибутов xmls в узле, если:

1. Попробуете добавить пространства имен после того, как сгенерируете все узлы. Как только вы впишите пространство имен в корневой элемент Вы автоматом получите тот же пустой xmlns="";

2. Попробуете удалить атрибут из узла. Этот вариант, на кажущуюся простоту, тоже не проходит. Пример удаления атрибута из узла:

Node:=ADoc.DocumentElement.ChildNodes.FindNode('title');
Node.AttributeNodes.Remove(Node.AttributeNodes['xmlns']);

При выполнении этого кода функция Remove вернет Вам 1, т.е. вроде бы атрибут удален...а документ получим опять "корявый".

3. Не помогли и манипуляции с набором свойств Options у документа.

Если Вы намеревались использоватькакой-то вариант из предложенных выше - не используйте. Всё равно не поможет. Зачаток решения проблемки нагуглился на одном из буржуйских форумах, посвященных работе с MSXML в C++. В Delphi решение проблемы с пустыми xmlns решается следующим образом (на примере того же документа):

ADoc:=NewXMLDocument;
ADoc.Active:=true;
Root:=ADoc.AddChild('entry');
for I:=0 to High(clNameSpaces) do
Root.DeclareNamespace('','http://www.w3.org/2005/Atom');
Node:=ADoc.CreateElement('title','http://www.w3.org/2005/Atom'); //создали узел
Node.Text:='TestCelenda'; //присвоили значение
ADoc.DocumentElement.ChildNodes.Add(Node); //записали документ

Если выполнить этот код получим нормальный правильный XML-документ, без пустых xmlns. Как оказалось, этот вариант работы с узлами является единственно правильным, когда в документе используются пространства имен...Ну что ж, с xmlns  я имел дело впервые и, как говориться "Век живи - век учись". Надеюсь эта заметка поможет кому-нибудь избежать лишних проблем при работе с XML в Delphi.

-----------------------------------
Если у Вас возникло острое желание выделиться из толпы, то возьмите лимузин напрокат в москве и покажите кто в городе хозяин.

Ну, а для тех, кто живёт в свое удовольствие и не заморачивается на диетах, лучшей пищей будет свинина и другие мясные продукты.
-----------------------------------
Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (4)

WP_Cloudy
  • Семен пишет:

    Все решения выше приведенные не очень красивые вот нормальный вариант:

    NewXMLDocument.GetDocBinding(‘entry’, TXMLentry,’http://www.w3.org/2005/Atom‘) as IXMLentry;

    в итоге добавится только в entry тег xmlns.

  • Вадим пишет:

     
    А есть ли какой-то компонент, или какой-то способ записи действия пользователя в XML?
    Это к вопросу о автоматизации действий. Есть программы для автоматической рассылки объявлений, регистрации в каталогах. Принцип там такой. Пользователь настраивает данные для автоматической регистрации, они заносятся в blob поле в базе данных в виде xml потом когда пользователь нажимает кнопку регистрация, программа считывает оттуда инструкции для каждого сайта свои, и выполняет автоматически действия, как по макросу. Вы знаете, в какую примерно сторону копать, чтобы реализовать нечто подобное?
    Спасибо.

  • Vlad пишет:

    Ну было дела, лет эдак 5 назад писал для себя авторегалку в каталогах сайтов. Но только зачем же для таких простых операций делать такие сложные финты ушами типа «данные для автоматической регистрации, они заносятся в blob поле в базе данных в виде xml«. Во-первых, данные будут скорее не для каждого сайта свои, а для каждого движка сайта свои — иначе нафиг такая регалка для которой сначала надо ВСЕ данные записать, а потом она будет регать? Не проще самому сразу руками все забить в формы на сайтах :).
    В какую сторону двигаться:
    1. Работа с простейшими (может даже однотабличными) базами данных или просто с XML для хранения необходимых сведений типа e-mail, адрес сайта, явки/пароли и т.д.
    2. Работа с DOM (Document Object Model) для того, чтобы полученные из БД данные правильно вставить в нужных местах формы на сайте.
    3. Если не нравится DOM, то работа с HTTP-протоколом, а именно надо научиться пользоваться каким-нибудь сниффером и правильно составлять POST/GET-запросы на сайт с целью авторегистрации «вслепую», т.е. без загрузки страниц сайта.
    Ну, а как уж вы организуете хранение — дело сугубо личное, я б сначала оценил вообще с какими движками придётся иметь дело, подобрал бы те данные котороые нужны всегда, какие нет и уже исходя из этого составлял бы базу.

  • Вадим пишет:

     
    Большое СПСИИБО!!!!
    Последнее предложение натолкнуло на поисковый запрос:
    (хранение данных в xml на delphi)
    и там нашел то, что хотел понять.
    Зачем так сложно, это просто описал то, что обнаружил изучая готовую аналогичную программу. Данные там действительно заносятся в базу после первой ручной регистрации, но потом уже в следующий раз, когда нужно зарегистрировать другой сайт, иди подать повторно объявление то поля заполняются сами. Можно пройдя руками по 12 доскам запустить поиск однотипных форм, тогда программа просмотрит все ссылки, которые без авто регистрации, и попробует сопоставить имеющиеся на страницах форы с теми, которые уже однажды были заполнены.
    Под несколько движков писать, это не актуально, так как большая часть каталогов и досок, по крайней мере тех, которые представляют интерес имеют свои названия полей. Есть идея по outerText анализировать страницу, и по найденным возле поля слову заносить туда автоматом значение, но так не в одной готовой программе не делается и пока ума не хватает.

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник