Д. Стефенс - C++. Сборник рецептов
- Название:C++. Сборник рецептов
- Автор:
- Жанр:
- Издательство:КУДИЦ-ПРЕСС
- Год:2007
- Город:Москва
- ISBN:5-91136-030-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Д. Стефенс - C++. Сборник рецептов краткое содержание
Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.
C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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 пространства имен
if (uri != xmlns)
throw runtime_error(
string("wrong namespace uri ") + toNative(uri)
);
if (localname == animal) {
// Добавить в список объект Animal; это будет
// "текущий объект Animal"
animalList_.push_back(Animal());
} else if (localname != animalList) {
Animal& animal = animalList_.back();
if (localname == vet) {
// Мы встретили элемент "ветеринар".
animal.setVeterinarian(contactFromAttributes(attrs));
} else if (localname == trainer) {
// Мы встретили элемент "дрессировщик".
animal.setTrainer(contactFromAttributes(attrs));
} else {
// Мы встретили элемент "кличка", "вид животного" или
// "дата рождения". Их содержимое будет получено
// при обратном вызове функции characters().
currentText_.clear();
}
}
}
// Если текущий элемент представляет кличку, вид животного или дату
// рождения, используйте хранимый в currentText_ текст для установки
// соответствующего свойства текущего объекта Animal.
void endElement(
const XMLCh *const uri, // URI пространства имен
const XMLCh *const localname, // имя тега без префикса NS
const XMLCh *const qname) // имя тега + префикс NS
{
static XercesString animalList = fromNative("animal-list");
static XercesString animal = fromNative("animal");
static XercesString name = fromNative("name");
static XercesString species = fromNative("species");
static XercesString dob = fromNative("dateOfBirth");
if (localname!= animal && localname!= animalList) {
// currentText_ содержит текст элемента, который был
// добавлен. Используйте его для установки свойств текущего
// объекта Animal.
Animal& animal = animalList_.back();
if (localname == name) {
animal setName(toNative(currentText_));
} else if (localname == species) {
animal.setSpecies(toNative(currentText_));
} else if (localname == dob) {
animal.setDateOfBirth(toNative(currentText_));
}
}
}
// Получает уведомления, когда встречаются символьные данные
void characters(const XMLCh* const chars,
const unsigned int length) {
// Добавить символы в конец currentText_ для обработки методом
// endElement()
currentText_.append(chars, length);
}
private:
vector& animalList_;
XercesString currentText_;
};
Пример 14.7. SAX2 ErrorHandler
#include // runtime_error
#include
// Получает уведомления об ошибках.
class CircusErrorHandler : public DefaultHandler {
Интервал:
Закладка: