inline XercesString fromNative(const char* str) {
boost::scoped_array ptr(xercesc::XMLString::transcode(str));
return XercesString(ptr.get());
}
Здесь ptrстановится обладателем возвращенной функцией transcode()строки с нулевым завершающим символом и освобождает ее, даже если конструктор XercesStringвыбрасывает исключение std::bad_alloc.
14.3. Синтаксический анализ сложного документа XML
Проблема
Имеется некоторый набор данных, хранимых в документе XML, внутри которого используется DTD или применяются пространства имен XML. Требуется выполнить синтаксический анализ документа и превратить содержащиеся в нем данные в набор объектов C++.
Решение
Используйте реализацию Xerces в виде программного интерфейса SAX2 (простой программный интерфейс для XML, версия 2.0). Во-первых, создайте класс, производный от xercesc::ContentHandler; этот класс будет получать уведомления с информацией о структуре и содержимом вашего документа XML по мере его анализа. Затем при желании можно создать класс, производный от xercesc::ErrorHandler, для получения предупреждений и сообщений об ошибках. Сконструируйте парсер типа xercesc::SAX2XMLReader, зарегистрируйте экземпляры классов вашего обработчика, используя методы парсера setContentHandler()и setErrorHandler(). Наконец, вызовите метод парсера parse(), передавая в качестве аргумента полное имя файла, в котором содержится ваш документ.
Например, пусть требуется выполнить синтаксический анализ документа XML animals.xml , приведенного в примере 14.1, и сконструировать вектор std::vectorобъектов Animal, представляющих животных, перечисленных в этом документе. (Определение класса Animalдается в примере 14.2.) В примере 14.3 я показываю, как можно это сделать, используя TinyXml. Для усложнения задачи добавим в документ пространства имен, как показано в примере 14.5.
Пример 14.5. Список цирковых животных, в котором используются пространства имен XML
Herby
elephant
1992-04-23
Для анализа этого документа с помощью SAX2 определите ContentHandler, как показано в примере 14.6, и ErrorHandler, как показано в примере 14.7. Затем сконструируйте SAX2XMLReader, зарегистрируйте ваши обработчики и запустите парсер. Это проиллюстрировано в примере 14.8.
Пример 14.6. Применение SAX2 ContentHandler для синтаксического анализа документа animals.xml
#include // runtime_error
#include
#include
#include // Содержит реализации без
// операций для различных
// обработчиков, используемых
#include "xerces_strings.hpp" // в примере 14.4
#include "animal.hpp"
using namespace std;
using namespace xercesc;
// Возвращает экземпляр Contact, построенный
// на основе заданного набора атрибутов
Contact contactFromAttributes(const Attributes &attrs) {
// Для повышения эффективности хранить часто используемые строки
// в статических переменных
static XercesString name = fromNative("name");
static XercesString phone = fromNative("phone");
Contact result; // Возвращаемый объект Contact.
const XMLCh* val; // Значение атрибута name или phone.
// Установить имя объекта Contact.
if ((val = attrs.getValue(name.c_str())) != 0) {
result.setName(toNative(val));
} else {
throw runtime_error("contact missing name attribute");
}
// Установить номер телефона для объекта Contact.
if ((val = attrs.getValue(phone.c_str())) != 0) {
result.setPhone(toNative(val));
} else {
throw runtime_error("contact missing phone attribute");
}
return result;
}
// Реализует обратные вызовы, которые получают символьные данные и
// уведомления о начале и конце элементов
class CircusContentHandler : public DefaultHandler {
public:
CircusContentHandler(vector& animalList) :
animalList_(animalList) {}
// Если текущий элемент представляет ветеринара или дрессировщика
// используйте attrs для конструирования объекта Contact для текущего
// Animal; в противном случае очистите currentText_, подготавливая
// обратный вызов characters()
void startElement(
const XMLCh *const uri, // URI пространства имен
const XMLCh *const localname, // имя тега без префикса NS
const XMLCh *const qname, // имя тега + префикс NS
const Attributes &attrs) // атрибуты элементов
{
static XercesString animalList = fromNative("animalList");
static XercesString animal = fromNative("animal");
static XercesString vet = fromNative("veterinarian");
static XercesString trainer = fromNative("trainer");
static XercesString xmlns =
fromNative("http://www.feldman-family-circus.com");
// проверить URI пространства имен
Читать дальше