KnigaRead.com/

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

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Д. Стефенс, "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.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*