ΠΡΠΈΠΌΠ΅Ρ 14.1. ΠΠΎΠΊΡΠΌΠ΅Π½Ρ XML ΡΠΎ ΡΠΏΠΈΡΠΊΠΎΠΌ ΠΆΠΈΠ²ΠΎΡΠ½ΡΡ ΡΠΈΡΠΊΠ°
<?xml version="1.0" encoding="UTF-8"?>
<!- ΠΠΈΠ²ΠΎΡΠ½ΡΠ΅ ΡΠΈΡΠΊΠ° Feldman Family Circus -->
<animalList>
<animal>
<name>Herby</name>
<species>elephant</species>
<dateOfBirth>1992-04-23</dateOfBirth>
<veterinarian name="Dr. Hal Brown" phone="(801)595-9627"/>
<trainer name="Bob Fisk" phone=(801)881-2260"/>
</animal>
<animal>
<name>Sheldon</name>
<species>parrot</species>
<dateOfBirth>1998-09-30</dateOfBirth>
<veterinarian name="Dr Kevin Wilson" phone="(801)466-6498"/>
<trainer name="Eli Wendel" phone="(801)929-2506"/>
</animal>
<animal>
<name>Dippy</name>
<species>penguin</species>
<dateOfBirth>2001-06-08</dateOfBirth>
<veterinarian name= "Dr. Barbara Swayne" phone="(801)459-7746"/>
<trainer name="Ben Waxman" phone="(801)882-3549"/>
</animal>
</animalList>
ΠΡΠΈΠΌΠ΅Ρ 14.2 ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΊΠ»Π°ΡΡΠ° Animal. Animal ΠΈΠΌΠ΅Π΅Ρ ΠΏΡΡΡ Π΄Π°Π½Π½ΡΡ -ΡΠ»Π΅Π½ΠΎΠ², ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΡ ΠΊΠ»ΠΈΡΠΊΠ΅, Π²ΠΈΠ΄Ρ, Π΄Π°ΡΠ΅ ΡΠΎΠΆΠ΄Π΅Π½ΠΈΡ, Π²Π΅ΡΠ΅ΡΠΈΠ½Π°ΡΡ ΠΈ Π΄ΡΠ΅ΡΡΠΈΡΠΎΠ²ΡΠΈΠΊΡ ΠΆΠΈΠ²ΠΎΡΠ½ΠΎΠ³ΠΎ. ΠΠ»ΠΈΡΠΊΠ° ΠΈ Π²ΠΈΠ΄ ΠΆΠΈΠ²ΠΎΡΠ½ΠΎΠ³ΠΎ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡΡΡ ΡΡΡΠΎΠΊΠ°ΠΌΠΈ ΡΠΈΠΏΠ° std::string, Π΄Π°ΡΠ° Π΅Π³ΠΎ ΡΠΎΠΆΠ΄Π΅Π½ΠΈΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΡΠΈΠΏΠΎΠΌ boost::gregorian::date ΠΈΠ· Boost.Date_Time, Π° Π΅Π³ΠΎ Π²Π΅ΡΠ΅ΡΠΈΠ½Π°Ρ ΠΈ Π΄ΡΠ΅ΡΡΠΈΡΠΎΠ²ΡΠΈΠΊ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡΡΡ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°ΠΌΠΈ ΠΊΠ»Π°ΡΡΠ° Contact, ΠΊΠΎΡΠΎΡΡΠΉ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ ΡΠ°ΠΊΠΆΠ΅ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ΅ 14.2. ΠΡΠΈΠΌΠ΅Ρ 14.3 ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ TinyXml Π΄Π»Ρ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Π°Π½Π°Π»ΠΈΠ·Π° Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ° animals.xml, ΠΏΡΠΎΡΠΌΠΎΡΡΠ° ΡΠ°Π·ΠΎΠ±ΡΠ°Π½Π½ΠΎΠ³ΠΎ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ° ΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π²Π΅ΠΊΡΠΎΡΠ° std::vector ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Animal, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΈΠ·Π²Π»Π΅ΡΠ΅Π½Π½ΡΠ΅ ΠΈΠ· Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ° Π΄Π°Π½Π½ΡΠ΅.
ΠΡΠΈΠΌΠ΅Ρ 14.2. ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΎΡΠ½ΡΠΉ ΡΠ°ΠΉΠ» animal.hpp
#ifndef ANIMALS_HPP_INCLUDED
#define ANIMALS_HPP_INCLUDED
#include <ostream>
#include <string>
#include <stdexcept> // runtime_error
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/regex.hpp>
// ΠΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ Π²Π΅ΡΠ΅ΡΠΈΠ½Π°ΡΠ° ΠΈΠ»ΠΈ Π΄ΡΠ΅ΡΡΠΈΡΠΎΠ²ΡΠΈΠΊΠ°
class Contact {
public:
Contact() {}
Contact(const std::string& name, const std::string& phone) :
name_(name) {
setPhone(phone);
}
std::string name() const { return name_; }
std::string phone() const { return phone_; }
void setName(const std::string& name) { name_ = name; }
void setPhone(const std::string& phone) {
using namespace std;
using namespace boost;
// ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ Boost.Regex, ΡΡΠΎΠ±Ρ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎ ΡΠ΅Π»Π΅ΡΠΎΠ½
// Π·Π°Π΄Π°Ρ Π² ΡΠΎΡΠΌΠ΅ (ddd)ddd-dddd
static regex pattern("\\([0-9]{3}\\)[0-9]{3}-[0-9]{4}");
if (!regex_match(phone, pattern)) {
throw runtime_error(string("bad phone number:") + phone);
}
phone_ = phone;
}
private:
std::string name_;
std::string phone_;
};
// Π‘ΡΠ°Π²Π½ΠΈΡΡ Π½Π° ΡΠ°Π²Π΅Π½ΡΡΠ²ΠΎ Π΄Π²Π° ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΠΊΠ»Π°ΡΡΠ° Contact; ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² ΡΠ΅ΡΠ΅ΠΏΡΠ΅
// 14.9 (Π΄Π»Ρ ΠΏΠΎΠ»Π½ΠΎΡΡ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΡΠ°ΠΊΠΆΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ operator!=)
bool operator--(const Contact& lhs, const Contact& rhs) {
return lhs.name() == rhs.name() && lhs.phone() == rhs.phone();
}
// ΠΠ°ΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡ ΠΊΠ»Π°ΡΡΠ° Contact Π² ΠΏΠΎΡΠΎΠΊ ostream
std::ostream& operator(std::ostream& out, const Contact& contact) {
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 <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 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");
}
// ΠΡΠΎΡΠΈΡΠ°ΡΡ ΡΠ»Π΅ΠΌΠ΅Π½Ρ Π΄Π°ΡΡ ΡΠΎΠΆΠ΄Π΅Π½ΠΈΡ
element = element->NextSiblingElement();
if (element && strcmp(element->Value(), "dateOfBirth") == 0) {
// Π’ΡΠ΅ΡΡΠΈΠΌ Π΄ΠΎΡΠ΅ΡΠ½ΠΈΠΌ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠΌ animal ΡΠ²Π»ΡΠ΅ΡΡΡ Π΄Π°ΡΠ° ΡΠΎΠΆΠ΄Π΅Π½ΠΈΡ
// (ΡΠ»Π΅ΠΌΠ΅Π½Ρ "dateOfBirth"));
// ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ Π΅Π³ΠΎ ΡΠ΅ΠΊΡΡΠΎΠ²ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ Π΄Π°ΡΡ
// ΡΠΎΠΆΠ΄Π΅Π½ΠΈΡ Π² ΠΎΠ±ΡΠ΅ΠΊΡΠ΅ result
result.setDateOfBirth(textValue(element));
} else {
throw runtime_error("no dateOfBirth attribute");