<< " species=" << animal.species() << ";\n"
<< date-of-birth=" << animal.dateOfBirth() << ";\n"
<< " veterinarian=" << animal.veterinarian() << ";\n"
<< " trainer=" << animal.trainer() << ";\n"
<< "}";
return out;
}
#endif // #ifndef ANIMALS_HPP_INCLUDED
Пример 14.3. Синтаксический анализ animals.xml с помощью TinyXml
#include <exception>
#include <iostream> // cout
#include <stdexcept> // runtime_error
#include <cstdlib> // EXIT_FAILURE
#include <cstring> // strcmp
#include <vector>
#include <tinyxml.h>
#include "animal.hpp"
using namespace std;
// Извлекает текстовое содержимое элемента XML
const char* textValue("TiXmlElement* e) {
TiXmlNode* first = fi->FirstChild();
if (first != 0 && first == e->LastChild() &&
first->Type() == TiXmlNode::TEXT) {
// элемент «е» имеет один дочерний элемент типа TEXT;
// возвратить дочерний элемент
return first->Value();
} else {
throw runtime_error(string("bad ") + e->Value() + " element");
}
}
// Конструирует объект класса Contact из элементов ветеринара или
// дрессировщика ("veterinarian" или "trainer")
Contact nodeToContact(TiXmlElement* contact) {
using namespace std;
const char *name, *phone;
if (contact->FirstChild() == 0 &&
(name = contact->Attribute("name")) &&
(phone = contact->Attribute("phone"))) {
// Элемент contact не имеет дочерних элементов и имеет атрибуты имени
// и телефона ("name" и "phone"); используйте эти значения для
// конструирования объекта Contact
return Contact(name, phone);
} else {
throw runtime_error(string("bad ") + contact->Value() + " element");
}
}
// Конструирует объект Animal из элемента животного ("animal")
Animal nodeToAnimal(TiXmlElement* animal) {
using namespace std;
// Убедиться, что animal соответствует элементу "animal"
if (strcmp(animal->Value(), "animal") != 0) {
throw runtime_error(string("bad animaclass="underline" ") + animal->Value());
}
Animal result; // Возвратить значение
TiXmlElement* element = animal->FirstChildElement();
// Прочитать элемент клички животного
if (element && strcmp(element->Value(), "name") == 0) {
// Первым дочерним элементом объекта animal является кличка (элемент
// name"); используйте ее текстовое значение для установки клички
// в объекте result
result.setName(textValue(element));
} else {
throw runtime_error("no name attribute");
}
// Прочитать элемент вида животного
element = element->NextSiblingElement();
if (element && strcmp(element->Value(), species") == 0) {
// Вторым дочерним элементом animal является вид животного
// (элемент "species"); используйте его текстовое значение для
// установки вида в объекте result
result.setSpecies(textValue(element));
} else {
throw runtime_error(""no species attribute");
}
// Прочитать элемент даты рождения
element = element->NextSiblingElement();
if (element && strcmp(element->Value(), "dateOfBirth") == 0) {
// Третьим дочерним элементом animal является дата рождения
// (элемент "dateOfBirth"));
// используйте его текстовое значение для установки даты
// рождения в объекте result
result.setDateOfBirth(textValue(element));
} else {
throw runtime_error("no dateOfBirth attribute");
}
// Прочитать элемент ветеринара
element = element->NextSiblingElement();
if (strcmp(element->Value(), "veterinarian") == 0) {
// Четвертым дочерним элементом animal является ветеринар (элемент
// "veterinarian"); используйте его для конструирования объекта
// Contact и установки имени ветеринара в объекте result
result.setVeterinarian(nodeToContact(element));
} else {
throw runtime_error("no veterinarian attribute");
}
// Прочитать элемент дрессировщика
element = element->NextSiblingElement();
if (strcmp(element->Value(), "trainer") == 0) {
// Пятым элементом animal является дрессировщик (элемент "trainer");
// используйте его для конструирования объекта
// Contact и установки дрессировщика в объекте result
result.setTrainer(nodeToContact(element));
} else {
throw runtime_error("no trainer attribute");
}
// Убедиться в отсутствии других дочерних элементов
element = element->NextSiblingElement();
if (element != 0) {
throw runtime_error(
string("unexpected element:") + element->Value()
);
}
return result;
}
int main() {
using namespace std;
try {
vector<Animal> animalList;
// Обработать "animals.xml"
TiXmlDocument doc("animals.xml");
if (!doc.LoadFile())
throw runtime_error("bad parse");
// Убедиться, что корневым является список животных
TiXmlElement* root = doc.RootElement();
if (strcmp(root->Value(), "animalList") != 0) {
throw runtime_error(string("bad root: ") + root->Value());
}
// Просмотреть все дочерние элементы корневого элемента, заполняя
// список животных
for (TiXmlElement* animal = root->FirstChildElement();