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 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();
animal; animal = animal->NextSiblingElement()) {
animalList.push_back(nodeToAnimal(animal));
}
// Напечатать клички животных
for (vector::size_type i = 0, n = animalList.size(); i < n; ++i) {
cout << animalList[i] << "\n";
}
} catch (const exception& e) {
cout << e.what() << "\n";
return EXIT_FAILURE;
}
}
Обсуждение
TinyXml (буквально «крошечный XML») очень хорошо подходит в тех случаях, когда требуется выполнять несложную обработку документов XML. Дистрибутив исходных текстов этой библиотеки небольшой, ее легко построить и интегрировать в проекты, и она имеет очень простой интерфейс. Она также имеет очень либеральную лицензию. Главными ограничениями TinyXml являются невосприимчивость к пространствам имен XML, невозможность контроля DTD или схемы, а также невозможность анализа документов XML с внутренним DTD. Если вам требуется какая-то из этих функций или какая-нибудь XML-технология, как, например, XPath или XSLT, то необходимо воспользоваться другими библиотеками, рассмотренными в данной главе.
На выходе парсера TinyXml получается документ XML в виде дерева, узлы которого представляют элементы, текст, комментарии и другие компоненты документа XML. Корень дерева представляет собственно документ XML. Такое иерархическое представление документа называется объектной моделью документа (Document Object Model - DOM). Модель DOM, полученная парсером TinyXml, аналогична модели, разработанной консорциумом W3C (World Wide Web Consortium), хотя она и не полностью соответствует спецификации W3C. Вследствие приверженности библиотеки TinyXml принципам минимализма модель TinyXml DOM проще W3С DOM, однако она обладает меньшими возможностями.
Получить доступ к узлам дерева, представляющего документ XML, можно с помощью интерфейса TiXmlNode, который содержит методы, обеспечивающие доступ к родительскому узлу, последовательный доступ ко всем дочерним узлам, удаление и добавление дочерних узлов. Каждый узел является экземпляром некоторого производного типа; например, корень дерева является экземпляром TiXmlDocument, узлы элементов являются экземплярами TiXmlElement, а узлы, представляющие текст, являются экземплярами TiXmlText. Тип TiXmlNodeможно определить с помощью его метода Туре(); зная тип узла, вы можете получить конкретное его представление с помощью таких методов, как toDocument(), toElement()и toText(). Эти производные типы содержат дополнительные методы, характерные для узлов конкретного типа.
Читать дальше