качестве аргумента полное имя файла, в котором содержится ваш документ.
Например, пусть требуется выполнить синтаксический анализ документа XML std::vector
объектов Animal
, представляющих животных, перечисленных в этом документе. (Определение класса Animal
дается в примере 14.2.) В примере 14.3 я показываю, как можно это сделать, используя TinyXml. Для усложнения задачи добавим в документ пространства имен, как показано в примере 14.5.
<?xml version='1.0' encoding='UTF-8'?>
<!- Животные цирка Feldman Family Circus с использованием пространств имен -- >
<ffc:animalList xmlns:ffc='http://www.feldman-family-circus.com'>
<ffc:animal>
<ffc:name>Herby</ffc:name>
<ffc:species>elephant</ffc:species>
<ffc:dateOfBirth>1992-04-23</ffc:dateOfBirth>
<ffc:veterinarian name='Dr. Hal Brown' phone='(801)595-9627'/>
<ffc:trainer name='Bob Fisk' phone='(801)881-2260'/>
</ffc:animal>
<!- и т.д. -->
</ffc:animalList>
Для анализа этого документа с помощью SAX2 определите ContentHandler
, как показано в примере 14.6, и ErrorHandler
, как показано в примере 14.7. Затем сконструируйте SAX2XMLReader
, зарегистрируйте ваши обработчики и запустите парсер. Это проиллюстрировано в примере 14.8.
#include <stdexcept> // runtime_error
#include <vector>
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/sax2/DefaultHandler.hpp> // Содержит реализации без
// операций для различных
// обработчиков, используемых
#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<Animal>& 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) {