WordPress. Работа с XML-RPC в DelphiИсточник: webdelphi
Источник: webdelphi Сегодня решил немного продолжить тему работы с XML-RPC в WordPress. Как это обычно со мной бывает, идея родилась в момент чтения случайного блога, вздумалось взглянуть на работу с постами в блоге и, заодно, попробовать написать что-нибудь под свои нужды. Естественно программу я сегодня не выложу, но некоторые выкладки, листинги и идеи в посте будут присутствовать. Вкратце работу с XML-RPC я рассматривал в посте "XML-RPC в Delphi. Первое знакомство с WordPress изнутри." Сегодня попробуем продвинуться дальше в своей работе и использовать несколько взаимосвязанных методов для получения определенной информации из блога. Конкретизируем цель на сегодня: необходимо получить данные по постам в блоге, используя доступные методы из API WordPress . Для достижения поставленной цели нам понадобятся следующие модули Delphi: XMLIntf , xmldom , XMLDoc и библиотека synapce или компонент Indy idHTTP (кому как угодно). 1. Тестируем соединение с блогом. Полагаю, что первое, что следует сделать - это проверить корректность работы с блогом на предмет следующих возможных ошибок: 1. В блоге отключена возможность использования XML-RPC 2. Пользователь предоставил некорректные данные (url, логин или пароль). Для проверки возможности работы с XML-RPC в блоге достаточно воспользоваться методом demo.sayHello . Если ответом будет строка "Hello" , значит всё в порядке и можно приступать к следующему шагу проверки. Для выполнения этой проверки нам потребуется выполнить три простенькие задачки:
Формируем XML-документ, который должен выглядеть так: <methodCall> <methodName>demo.sayHello</methodName> <params> <param> <value> <string>test</string> </value> </param> </params> </methodCall> Для этого воспользуемся интерфейсом IXMLDocument:
Так как сам по себе XML-документ достаточно простой, то я позволил себе немного "похалявить" и последней строкой кода записал сразу все узлы и значение единственного параметра для нашего метода.
Что мне нравится в Synapce, так это то, что не требуется лишних "телодвижений" в плане заполнения заголовков Content-Length , Content-Type и пр. Конечно никто не мешает заполнить все возможные заголовки самому, но можно обойтись и так, как показал я выше - всё на автомате.
В соответствии со спецификацией XML-RPC сообщения об ошибках содержится в узле с названием fault. Следовательно, применительно к нашему случаю достаточно проверить наличие такого узла в ответном XML-документе - если его нет, то значит проверка прошла успешно, был сформирован корректный запрос и XML-RPC работает исправно. 1. Сформировать "скелет" документа 2. Записать в документ все необходимые параметры, учитывая типы данных 3. Отправить запрос и получить ответ от сервера 4. Проанализировать ответ и, если в ответе содержится сообщение об ошибке, то правильно его прочитать Все эти четыре шага я сделал отдельными методами класса. Под "скелетом" документа я понимаю следующее содержимое: <methodCall> <methodName>MethodName</methodName> <params> </params> </methodCall> То есть часть документа, содержащая имя метода и узел params без содержимого. Дальше на останется только правильно заполнить список параметров. Чем мы сейчас и займемся. Всего в XML-RPC предусмотрено использование шести простых типов данных: 1. int и i4 - целые числаinteger) 2. double - дробные числа 3. string - строки 4. base64 - закодированная строка 5. dateTime.iso8601 - дата/время 6. boolean Заводим новый тип данных:
С помощью значений этого типа будем определять тэг для значения параметра. Так как операции создания "скелета" документа и добавления параметров метода разнесены по разным функциям, то создадим ещё один вспомогательный тип данных:
Теперь сам метод добавления параметра в документ:
Этот метод работает только в случае записи простого типа. При работе со структурами необходимо доработать алгоритм. Теперь про анализ сообщений об ошибке. Рассмотрим пример того, как выглядит сообщение об ошибке в XML-RPC: <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value> <int>403</int> </value> </member> <member> <name>faultString</name> <value> <string>Bad login/pass combination.</string> </value> </member> </struct> </value> </fault> </methodResponse> Сообщение об ошибке приходит нам в структуре. Причём, если считать, что теги member нумеруются от нуля, то каждый чётный элемент структуры - это код ошибки, а нечётный - текст ошибки. Следовательно метод обработки сообщений об ошибке может выглядеть так:
Здесь код и текст ошибки записывается в TStringList. Думаю, что при необходимости можно легко сделать, чтобы код и текст читались в разные списки или массивы. Нам пока это не требуется. Отправку документа мы уже рассматривали, поэтому сразу привожу метод проверки данных на корректность:
Если пришло сообщение об ошибке, то записываем сообщение в переменную Error. В данном случае структура содержит только одно сообщение об ошибке - поэтому я так легко прописал:
Итак, две проверки сделаны и мы определили, что XML-RPC включен и работает исправно, а пользователь ввёл корректные данные логина и пароля и может работать с API WordPress. Что дальше? А дальше начинаем основную работу - получаем данные по комментариям в блоге. 2. Получаем данные о постах блога. Итак, что предоставляет в наше распоряжение WordPress. Сначала сделаем кратки обзор методов из xmlrpc.php. wp.getPostStatusList - выводит значения для статуса поста. По сути на выходе будем имеет четыре строки: "draft", "pending", "private", "publish". Пока этот метод нам бесполезен. blogger.getRecentPosts - эта функция уже из API Blogger, но поддерживается в WordPress. На выходе будем иметь последние посты блога, включая весь контент поста. Можно использовать метод, НО работа программы будет замедлена так как придётся "тягать" по Сети пост целиком. А если попробуем получить список постов блога целиком, то, видимо придётся ложиться спать, не дождавшись результата. Следовательно - пока оставляем метод в стороне. metaWeblog.getRecentPosts - аналогично предыдущему методу. mt.getRecentPostTitles - метод из MovableType API. Судя по названию - то, что нам надо. Смотрим описание метода. Метод возвращает список, содержащий заголовки постов блога. При этом контент в список не записывается. Входные параметры:
blogid всегда равен 1 (см. описание в xmlrpc.php) numberOfPosts - количество постов, которые необходимо вывести в список. Если параметр имеет значение больше, чем количество постов в блоге, то метод возвращает список всех постов. Осталось узнать, что из себя представляет этот список. А на выходе мы будем иметь массив структур, включающий в себя:
Замечательно. Воспользуемся этим методом, а заодно научимся анализировать сложные структуры ответа. Про создание запроса, думаю, писать не стоит. Процедура аналогична той, что рассмотрена выше. А на анализе ответа сервера остановимся подробно. Стем как выглядит тип struct (структура) мы познакомились при парсинге ответа, содержащего ошибку авторизации. Посмотрим, что из себя представляет массив. Массивы не имеют названия и описываются тегом <array>. Он содержит один элемент <data> и один или несколько дочерних элементов <value>, где задаются данные. В качестве элементов массива могут выступать любые другие типы в произвольном порядке, а также другие массивы - что позволяет описывать многомерные массивы. Так же можно описывать массив структур. Например, массив из четырех элементо будет выглядеть так: <array> <data> <value><i4>34</i4></value> <value><string>Привет, Мир!</string></value> <value><boolean>0</boolean></value> <value><i4>-34</i4></value> </data> </array> У нас на выходе из метода mt.getRecentPostTitles 1. Выделяем из XML-документа все элементы value 2. В каждом value читаем все элементы member 3. каждый второй дочерний элемент у member - данные по посту, которые необходимо запомнить. Начнем сразу с обработки ответа. Вводим новый тип данных:
Обрабатываем ответ сервера.
Соответственно, если получено сообщение об ошибке, то можно воспользоваться рассмотренной ранее функцией. На сегодня всё. В следующий раз продолжим работу с API и попробуем получить все комментарии из блога. |