out << contact.name() << " " << contact.phone(); return out;
}
// Класс Animal представляет животное
class Animal {
public:
// Конструктор по умолчанию класса Animal; этот конструктор будет вами
// использоваться чаще всего Animal() {}
// Конструирование объекта Animal с указанием свойств животного;
// этот конструктор будет использован в рецепте 14.9
Animal(const std::string& name,
const std::string& species, const std::string& dob,
const Contact& vet, const Contact& trainer) :
name_(name), species_(species), vet_(vet), trainer_(trainer) {
setDateOfBirth(dob)
}
// Функции доступа к свойствам животного
std::string name() const { return name_; }
std::string species() const { return species_; }
boost::gregorian::date dateOfBirth() const { return dob_; )
Contact veterinarian() const { return vet_; }
Contact trainer() const { return trainer_; }
// Функции задания свойств животного
void setName(const std::string& name) { name_ = name; }
void setSpecies(const std::string& species) { species_ = species; }
void setDateOfBirth(const std::string& dob) {
dob_ = boost::gregorian::from_string(dob);
}
void setVeterinarian(const Contact& vet) { vet_ = vet; }
void setTrainer(const Contact& trainer) { trainer_ = trainer; }
private:
std::string name_;
std::string species_;
boost::gregorian::date dob_;
Contact vet_;
Contact trainer_;
};
// Сравнение на равенство двух объектов Animal; используется в рецепте 14.9
// (для полноты следует также определить operator!=)
bool operator==(const Animal& lhs, const Animal& rhs) {
return lhs.name() == rhs.name() && lhs.species() == rhs.species() &&
lhs.dateOfBirth() == rhs.dateOfBirth() &&
lhs.veterinarian() == rhs.veterinarian() &&
lhs.trainer() == rhs.trainer();
}
// Записывает объект Animal в поток ostream
std::ostream& operator<<(std::ostream& out, const Animal& animal) {
out << "Animal {\n"
<< " name=" << animal.name() << ";\n"
<< " 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
#include // cout
#include // runtime_error
#include // EXIT_FAILURE
#include // strcmp
#include
#include
#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 animal: ") + 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");
}
// Прочитать элемент даты рождения
Читать дальше