Например, предположим, что у вас имеется XML-документ animalList
и содержит несколько дочерних элементов animal
, каждый из которых представляет одно животное, принадлежащее цирку Feldman Family Circus. Предположим также, что у вас имеется класс C++ с именем Animal
, и вам нужно сконструировать вектор std::vector
, состоящий из объектов Animal
, представляющих животных, перечисленных в документе.
<?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
для синтаксического анализа документа std::vector
объектов Animal
, используя извлеченные из документа данные.
#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,