`
Читать книги » Книги » Компьютеры и Интернет » Программирование » Д. Стефенс - C++. Сборник рецептов

Д. Стефенс - C++. Сборник рецептов

Перейти на страницу:

int main() {

 try {

  XalanInitializer init; // Инициализировать Xalan

  XalanTransformer xslt; // Конвертор XSLT.

  XSLTResultTarget html("animals.html"); // Результат работы xslt.

  // Выполнить синтаксический анализ исходного документа

  XSLTInputSource xml("animals.xml");

  XalanParsedSource* parsedXml = 0;

  if (xslt.parseSource(xml, parsedXml) != 0) {

   cout << "xml error: " << xslt.getLastError() << "n";

  }

  // Компилировать таблицу стилей.

  XSLTInputSource xsl("animals.xsl");

  XalanCompiledStylesheet* compiledXsl = 0;

  if (xslt.compileStylesheet(xsl, compiledXsl) != 0) {

   cout << "xml error: " << xslt.getLastError() << "n";

  }

  // Выполнить преобразование.

  if (xslt.transform(xml, xsl, html)) {

   cout << "xml error: " << xslt.getLastFrror() << "n";

  }

 } catch (const XMLException& e) {

  cout << "xml error: " << toNative(e.getMessage()) << "n";

  return EXIT_FAILURE;

 } catch (const exception& e) {

  cout << e.what() << "n";

  return EXIT_FAILURE;

 }

}

Смотри также

Рецепт 14.8.

14.8. Вычисление XPath-выражения

Проблема

Требуется извлечь информацию из документа XML, обработанного парсером, путем вычисления XPath-выражения.

Решение

Используйте библиотеку Xalan. Во-первых, выполните синтаксический анализ документа XML и получите указатель на xalanc::XalanDocument. Это можно сделать, используя экземпляры XalanSourceTreeInit, XalanSourceTreeDOMSupport и XalanSourceTreeParserLiaison, каждый из которых следующим образом определяется в пространстве имен xalanc.

#include <xercesc/framework/LocalFileInputSource.hpp>

#include <xalanc/XalanSourceTree/XalarSourceTreeDOMSupport.hpp>

#include <xalanc/XalanSourceTree/XalanSourceTreeInit.hpp>

#include <xalanc/XalanSourceTree/XalanSourceTreeParserLiaison.hpp>

...

int main() {

 ...

 // Инициализировать подсистему XalanSourceTree

 XalarSourceTreeInit init;

 XalanSourceTreeDOMSupport support;

 // Интерфейс доступа к парсеру

 XalanSourceTreeParserLiaison liaison(support);

 // Подключить DOMSupport к ParserLiaison

 support.setParserLiaison(&liaison);

 LocalFileInputSource src(место-расположения-документа);

 XalanDocument* doc = liaison.ParseXMLStream(doc);

 ...

}

Можно поступить по-другому и использовать парсер Xerces DOM для получения указателя на DOMDocument, как это сделано в примере 14.14, и затем использовать экземпляры XercesDOMSupport, XercesParserLiaison и XercesDOMWrapperParsedSource, каждый из которых определяется в пространстве имен xalanc для получения указателя на XalanDocument, соответствующего документу DOMDocument.

#include <xercesc/dom/DOM.hpp>

#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>

#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>

#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>

...

int main() {

 ...

 DOMDocument* doc = ...;

 XercesDOMSupport support;

 XercesParserLiaison liaison(support);

 XercesDOMWrapperParsedSource src(doc, liaison, support);

 XalanDocument* xalanDoc = src.getDocument();

 ...

}

На следующем шаге получите указатель на узел, выполняющий роль узла контекста при вычислении выражения XPath. Это можно сделать с помощью интерфейса DOM документа XalanDocument. Сконструируйте XPathEvaluator для вычисления выражения XPath и XalanDocumentPrefixResolver для разрешения префиксов пространств имен в документе XML. Наконец, вызовите метод XPathEvaluator::evaluate(), передавая в качестве аргументов DOMSupport, контекстный узел, XPath-выражение и PrefixResolver. Результат вычисления выражения возвращается в виде объекта типа XObjectPtr; тип допустимых операций над этим объектом зависит от типа его данных XPath, который можно узнать при помощи метода getType().

Например, пусть требуется извлечь список имен животных из документа animals.xml, представленного в примере 14.1. Вы можете это сделать, выполняя синтаксический анализ документа и вычисляя XPath-выражение animalList/animal/name/child::text() с использованием корня документа в качестве контекстного узла. Это проиллюстрировано в примере 14.23.

Пример 14.23. Вычисление ХРаth-выражения, используя Xalan

#include <cstddef> // size_t

#include <exception>

#include <iostream> // cout

#include <xercesc/dom/DOM.hpp>

#include <xercesc/parsers/XercesDOMParser.hpp>

#include <xercesc/sax2/DefaultHandler.hpp>

#include <xercesc/util/PlatformUtils.hpp>

#include <xalanc/DOMSupport/XalanDocumentPrefixResolver.hpp>

#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>

#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>

#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>

#include <xalanc/XPath/XObject.hpp>

#include <xalanc/XPath/XPathEvaluator.hpp>

#include "animal.hpp"

#include "xerces_strings.hpp"

using namespace std;

using namespace xercesc;

using namespace xalanc;

// Утилита RAII, которая инициализирует парсер и процессор XPath, освобождая

// ресурсы при выходе из области видимости

class XPathInitializer {

public:

 XPathInitializer() {

 XMLPlatformUtils::Initialize();

 XPathEvaluator::initialize();

}

~XPathInitializer() {

 XpathEvaluator::terminate();

 XMLPlatformUtils::Terminate();

}

private:

 // Запретить копирование и присваивание

 XPathInitializer(const XPathInitializer&);

 XPathInitializer& operator=(const XPathInitializer&);

};

// Получает уведомления об ошибках

class CircusErrorHandler : public DefaultHandler {

public:

 void error(const SAXParseException& e) {

  throw runtime_error(toNative(e.getMessage()));

 }

 void fatalError(const SAXParseException& e) { error(e); }

};

int main() {

 try {

  // Инициализировать Xerces и XPath и сконструировать парсер DOM.

  XPathInitializer init;

  XercesDOMParser parser;

  // Зарегистрировать обработчик ошибок

  CircusErrorHandler error;

  parser.setErrorHandler(&error);

  // Выполнить синтаксический анализ animals.xml.

  parser.parse(fromNative("animals.xml").c_str());

  DOMDocument* doc = parser.getDocument();

  DOMElement* animalList = doc->getDocumentElement();

  // Создать XalanDocument на основе doc.

  XercesDOMSupport support;

  XercesParserLiaison liaison(support);

  XercesDOMWrapperParsedSource src(doc, liaison, support);

  XalanDocument* xalanDoc = src.getDocument();

  // Вычислить XPath-выражение для получения списка

  // текстовых узлов, содержащих имена животных

  XPathEvaluator evaluator;

  XalanDocumentPrefixResolver resolver(xalanDoc);

  XercesString xpath =

   fromNative("animalList/animal/name/child::text()");

  XObjectPtr result =

   evaluator.evaluate(

    support,       // поддержка DOM

    xalanDoc,      // контекстный узел

    xpath.c_str(), // XPath-выражение

    resolver);     // функция разрешения пространства имен

  const NodeRefListBase& nodeset = result->nodeset();

  // Просмотр списка узлов и вывод имен животных

  for (size_t i = 0, len = nodeset.getLength(); i < len; ++i) {

   const XMLCh* name = nodeset.item(i)->getNodeValue().c_str();

   std::cout << toNative(name) << "n";

  }

 } catch (const DOMException& e) {

  cout << "xml error: " << toNative(e.getMessage()) << "n";

  return EXIT_FAILURE;

 } catch (const exception& e) {

  cout << e.what() << "n";

  return EXIT_FAILURE;

 }

}

Обсуждение

XPath — это язык поиска по образцу (pattern matching language), предназначенный для извлечения информации из документов XML. Основная конструкция XPath — выражение пути (path expression) поддерживает иерархический синтаксис ссылок на элементы, атрибуты и текстовые узлы на основе использования их имен, атрибутов, текстового содержимого, отношений наследования и других свойств. Кроме работы с наборами узлов язык XPath может обрабатывать строки, числа и булевы значения. XPath версии 2.0, которая в настоящее время не поддерживается библиотекой Xalan, использует даже более сложную модель данных, основанную на рекомендациях XML Schema. (См. рецепт 14.5.)

XPath-выражения вычисляются в контексте узла документа XML, называемого контекстным узлом, который используется для интерпретации связанной с ним конструкции, например, parent, child и descendant. В примере 14.23 я указал корень (root) документа XML в качестве контекстного узла; этот узел является родительским по отношению к корневому элементу документа XML, а также к любой инструкции обработки и комментариям верхнего уровня. При вычислении выражения с использованием корневого узла в качестве контекстного узла выражение пути animalList/animal/name/child::text() соответствует всем текстовым узлам, дочерним по отношению к элементам name, родительским элементом которых является animal, и чьим «дедушкой» является элемент animalList.

Перейти на страницу:

Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение Д. Стефенс - C++. Сборник рецептов, относящееся к жанру Программирование. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.

Комментарии (0)