Xalan-c++: возврат узла с XPath (ссылка на локальный указатель)

Я новичок в Xalan и Xerces, и я пытаюсь выбрать один конкретный узел с помощью XPath. Должна быть возможность вернуть данные xml по ссылке, но их также необходимо изменить, поэтому я сохранил их как DOMDocument, чтобы иметь доступ к данным через xerces для управления ими. У меня есть два метода: один для чтения XML-файла и проверки схемы, а другой для получения определенного узла. Я работаю с Visual Studio 2012 и, конечно же, библиотеками Xalan и Xerces. Я попытался создать один SSCCE, чтобы показать вам свою проблему:

Заголовочный файл:

#pragma once

#include <string.h>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xalanc/Include/PlatformDefinitions.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>

XALAN_CPP_NAMESPACE_USE
XERCES_CPP_NAMESPACE_USE

namespace CodeTest{
    class Test
    {
    public:
        Test(std::string schemaFilePath, std::string xmlFilePath){      
            mSchemaFilePath = schemaFilePath;
            mXMLFilePath = xmlFilePath;

            XMLPlatformUtils::Initialize(); 
            XalanTransformer::initialize();
            readXMLFile();
        }
        ~Test(){
            XalanTransformer::terminate();
            XMLPlatformUtils::Terminate(); 
        }
        const XalanNode* getNode(XalanDOMString& path)const;

    private:
        Test();
        Test(const Test&);
        void readXMLFile();
        std::string mSchemaFilePath;
        std::string mXMLFilePath;
        DOMDocument* mXMLDocument;
        DOMElement* mRootElement;
        XalanDocument* mXalanDocument;
        XalanDocument* convertXercesDomDocumentToXalanDocument();
    };
}

Исходный файл:

#include "Test.h"

#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xalanc/XPath/XPath.hpp>
#include <xalanc/XPath/XPathEvaluator.hpp>
#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>

namespace CodeTest{

    void Test::readXMLFile(){   

        XercesDOMParser xmlParser;
        if (xmlParser.loadGrammar(mSchemaFilePath.c_str(), Grammar::SchemaGrammarType) == NULL){
            fprintf(stderr, "couldn't load schema\n");
            return;
        }
        xmlParser.setValidationScheme(XercesDOMParser::Val_Auto);
        xmlParser.setDoNamespaces(true);
        xmlParser.setDoSchema(true);
        xmlParser.setValidationConstraintFatal(true);
        xmlParser.parse(mXMLFilePath.c_str());
        mXMLDocument = xmlParser.adoptDocument();
        mXMLDocument->normalize();
        mRootElement = mXMLDocument->getDocumentElement();
    }

    const XalanNode* Test::getNode(XalanDOMString& path)const{
        XPathEvaluator      theEvaluator;
        XercesParserLiaison theParserLiaison;
        XercesDOMSupport theDOMSupport(theParserLiaison);
        XSLTInputSource xmlInput = mXMLFilePath.c_str();
        XercesDOMWrapperParsedSource parsedSource(mXMLDocument, theParserLiaison, theDOMSupport, XalanDOMString(xmlInput.getSystemId()));       
        XalanDocument* xalanDocument = parsedSource.getDocument();
        const XalanNode* node = theEvaluator.selectSingleNode(theDOMSupport, xalanDocument, path.c_str());
        return node;
    }   
}

и моя основная функция:

#include "Test.h"
#include <string.h>

int main(){
    std::string schemaFile = "d:/testDate.xsd";
    std::string xmlFile = "d:/test.xml";
    CodeTest::Test xmlParser(schemaFile, xmlFile);  
    XalanDOMString path("personnel/person[1]"); 
    const XalanNode* node = xmlParser.getNode(path);        
    return 0;
}

Проблема в том, что мне нужно вернуть узел со всеми его свойствами по ссылке. Но проблема в том, что кивок — это всего лишь локальный указатель, который недействителен, если он находится вне области действия. Я уже пытался сохранить его как переменную-член, но право собственности на указатель принадлежит XercesDOMWrapperParsedSource, и я не могу создать его как глобальную переменную, потому что получаю сообщение об ошибке, что конструктор по умолчанию является закрытым.

Поэтому я надеюсь, что кто-нибудь из вас может дать мне несколько советов.


person KaHo    schedule 11.12.2013    source источник


Ответы (1)


Вы не можете оставить только XalanNode* и забыть обо всем остальном. Если вы хотите передать XmlNode вокруг своего приложения, вы должны инкапсулировать его в свой собственный класс, который будет внутренне содержать все, что * нужно XalanNode.

Чтобы продемонстрировать это, я собираюсь приложить несколько вспомогательных файлов, которые я использую в своем проекте. Эти файлы будут вставлены «как есть», т.е. вам, вероятно, придется немного потрудиться при их компиляции, так как они являются частью более крупного проекта и имеют некоторые зависимости, которые я не упомяну (такие как журналирование, boost::filesystem::path ; вы можете легко избавиться от этих зависимостей). Тем не менее, если это кому-то нужно, так что я думаю, что они легко адаптируют его под свой проект и поймут идею.

Предоставленные классы предназначены для загрузки XML-документа в память и позволяют читать его с использованием выражений XPath.

Вот пример использования моих классов.

#include "tools/xalan/XalanRegistration.h"
#include "tools/xalan/XmlDoc.h"
#include "tools/xalan/XmlNode.h"

tools::xalan::XmlNode do_stuff_and_get_node() {

    XmlDoc myDoc("file_to_load.xml");
    return myDoc.getNode("/path/to/my/node");

}

int main(){
    //this always goes to the main application scope
    tools::xalan::XalanRegistration xalan;

    //the rest may appear anywhere in your application

    const tools::xalan::XmlNode my_node = do_stuff_and_get_node();

    if (my_node.getBool("xpath/relative/to/my_node[@boolean_attr]")) {
        std::out << my_node.getString("xpath/relative/to/my_node/text()");
    }

    const tools::xalan::XmlNode other_node = my_node("other/node");

    //node holds internally the whole document so you can use also
    //absolute xpath
    auto more_nodes = other_node.getNodes("/i/want/more");
    for (const tools::xalan::XmlNode &node: more_nodes) {
        ...
    }
}

А вот и включенные классы (извините, если это не лучший способ прикрепить что-то большее на этом сайте)

Основная реализация находится в XalanXmlDoc, который содержит весь контекст, но не может быть скопирован. XmlDoc и XmlNode удобно оборачивают XalanXmlDoc, чтобы документ или узлы можно было легко передавать по приложению.

инструменты/xalan/XercesRegistration.h

#ifndef TOOLS_XERCES_XERCESREGISTRATION_H_
#define TOOLS_XERCES_XERCESREGISTRATION_H_

#include "NS-OPEN"

class XercesRegistration {
public:

    /**
     * This constructor calls:
     * XMLPlatformUtils::Initialize();
     */
    XercesRegistration();

    /**
     * This destructor calls:
     * XMLPlatformUtils::Terminate();
     */
    ~XercesRegistration();

};

#include "NS-CLOSE"
#endif 

инструменты/xalan/XercesRegistration.cpp

#include "XercesRegistration.h"

#include <xercesc/util/PlatformUtils.hpp>

#include "NS-OPEN"

XercesRegistration::XercesRegistration() {
    using xercesc::XMLPlatformUtils;

    //may throw xercesc::XMLException
    XMLPlatformUtils::Initialize();
}

XercesRegistration::~XercesRegistration() {
    using xercesc::XMLPlatformUtils;

    XMLPlatformUtils::Terminate();
}

#include "NS-CLOSE"

инструменты/xalan/XalanRegistration.h

#ifndef TOOLS_XALAN_XALANREGISTRATION_H_
#define TOOLS_XALAN_XALANREGISTRATION_H_

#include "tools/xerces/XercesRegistration.h"
#include <xalanc/XalanSourceTree/XalanSourceTreeInit.hpp>

#include "NS-OPEN"

/**
 * \brief XalanRegistration
 *
 * \author David Laštovička
 */
class XalanRegistration {
private:
    typedef xerces::XercesRegistration XercesRegistration;
    typedef xalanc::XalanSourceTreeInit XalanSourceTreeInit;

    //may throw xercesc::XMLException
    XercesRegistration xercesRegistration;

    /**
     * As seen in xalan-c-1.11/c/samples/SimpleXPathAPI/SimpleXPathAPI.cpp
     */
    XalanSourceTreeInit     theSourceTreeInit;

public:

    /**
     * \brief This constructor instantiates the object.
     */
    XalanRegistration();

    ~XalanRegistration();

};

#include "NS-CLOSE"
#endif 

инструменты/xalan/XalanRegistration.cpp

#include "XalanRegistration.h"

#include <xalanc/XPath/XPathEvaluator.hpp>

#include "NS-OPEN"

XalanRegistration::XalanRegistration() {
    using xalanc::XPathEvaluator;
    XPathEvaluator::initialize();
}

XalanRegistration::~XalanRegistration() {
    using xalanc::XPathEvaluator;
    XPathEvaluator::terminate();
}

#include "NS-CLOSE"

инструменты/ксалан/XmlDoc.h

#ifndef TOOLS_XALAN_XMLDOC_H_
#define TOOLS_XALAN_XMLDOC_H_

#include <memory>
#include <set>
#include "XalanXmlDoc.h"
#include "XmlNode.fwd.h"
#include "tools/exception/EntityNotFound.h"
#include "tools/exception/NotUnique.h"

#include "NS-OPEN"

/**
 * \brief XmlDoc is a simple reader for XML documents.
 *
 * It is meant to be used to:
 * - read only
 * - small documents fitting the memory
 * - fetching data from the document with XPath
 *
 * XmlDoc allows to obtain and pass around a XmlNode representing only
 * a part of the document.
 *
 * XmlDoc/XmlNode can be simply copied or moved around. All their copies
 * internally share one instance of XalanXmlDoc that is released when the last
 * XmlDoc/XmlNode is deleted.
 *
 * \author David Laštovička
 */
class XmlDoc {
private:

    typedef std::string string;
    typedef boost::filesystem::path path;
    template<class T> using Container = std::vector<T>;
    typedef tools::exception::EntityNotFound EntityNotFound;
    typedef tools::exception::NotUnique NotUnique;

    const std::shared_ptr<XalanXmlDoc> xalanXmlDoc;

public:

    /**
     * \brief This constructor instantiates the object.
     */
    XmlDoc(const path &source);

    XmlDoc(const std::shared_ptr<XalanXmlDoc> &xalanXmlDoc);

    XmlDoc(const XmlDoc &) = default;

    XmlDoc(XmlDoc &&) = default;

    XmlNode getRoot() const;

    string getString(const string &xpath) const
    THROW(EntityNotFound);

    Container<string> getStrings(const string &xpath) const;

    std::set<string> getDistinctStrings(const string &xpath) const;

    XmlNode getNode(const string &xpath) const
    THROW(EntityNotFound);

    Container<XmlNode> getNodes(const string &xpath) const;

};

#include "NS-CLOSE"

#endif /* TOOLS_XALAN_XMLDOC_H_ */

инструменты/ксалан/XmlDoc.cpp

#include "XmlDoc.h"

#include "XmlNode.h"

#include "tools/llog/common.h"

#include "NS-OPEN"

XmlDoc::XmlDoc(const path &source)
:   xalanXmlDoc(new XalanXmlDoc(source))
{
}

XmlDoc::XmlDoc(const std::shared_ptr<XalanXmlDoc> &xalanXmlDoc)
:   xalanXmlDoc(xalanXmlDoc)
{

}

auto XmlDoc::getRoot() const
-> XmlNode
{
    return getNode("/");
}

auto XmlDoc::getString(const string &xpath) const
THROW(EntityNotFound)
-> string
{
    //may throw EntityNotFound, NotUnique
    return xalanXmlDoc->getString(xpath);
}

auto XmlDoc::getStrings(const string &xpath) const
-> Container<string>
{
    return xalanXmlDoc->getStrings(xpath);
}

auto XmlDoc::getDistinctStrings(const string &xpath) const
-> std::set<string>
{
    using std::set;
    //ToDo use distinct-values once XPath 2 available in Xalan
    //auto depTypeCodeNodes = xmlDoc.getNodes("distinct-values(/module/dependencies/dependency/@type)");
    auto values = getStrings(xpath);
    set<string> res;
    for (auto value: values)
        res.insert(value);
    return res;
}

auto XmlDoc::getNode(const string &xpath) const
THROW(EntityNotFound)
-> XmlNode
{
    //may throw EntityNotFound, NotUnique
    return XmlNode(xalanXmlDoc,xalanXmlDoc->getNode(xpath));
}

auto XmlDoc::getNodes(const string &xpath) const
-> Container<XmlNode>
{
    using std::transform;
    auto xalanNodes = xalanXmlDoc->getNodes(xpath);
    Container<XmlNode> res;
    transform(
        xalanNodes.begin(), xalanNodes.end(),
        back_inserter(res),
        [this](const XalanXmlDoc::NodeHandle &xalanNode)->XmlNode
        {
            assert(xalanNode);
            return XmlNode(this->xalanXmlDoc,xalanNode);
        }
        );
    return res;
}

#include "NS-CLOSE"

инструменты/ксалан/XmlNode.h

#ifndef TOOLS_XALAN_XMLNODE_H_
#define TOOLS_XALAN_XMLNODE_H_

#include "XalanXmlDoc.h"
#include "XmlDoc.fwd.h"
#include "tools/exception/EntityNotFound.h"
#include "tools/exception/NotUnique.h"

#include "NS-OPEN"

/**
 * \brief XmlDoc
 *
 * \author David Laštovička
 */
class XmlNode {
private:
    typedef std::string string;
    template<class T> using Container = std::vector<T>;
    typedef tools::exception::EntityNotFound EntityNotFound;
    typedef tools::exception::NotUnique NotUnique;

    /**
     * In order to support move assignment and move operator this member
     * is not const
     */
    std::shared_ptr<XalanXmlDoc> xalanXmlDoc;

    /**
     * In order to support (the default) move assignment and move operator
     * implementation this member is not const.
     */
    XalanXmlDoc::NodeHandle node;

public:

    /**
     * Default constructor creates an empty node corresponding to this xml:
     * </>
     */
    XmlNode();

    XmlNode(
        const std::shared_ptr<XalanXmlDoc> &xalanXmlDoc,
        const XalanXmlDoc::NodeHandle &node
        );

    XmlNode(const XmlNode &) = default;

    XmlNode(XmlNode &&) = default;

    XmlDoc getDoc() const;

    string getString(const string &xpath) const
    THROW(EntityNotFound);

    string getString(const string &xpath, const string &defaultValue) const;

    Container<string> getStrings(const string &xpath) const;

    XmlNode getNode(const string &xpath) const
    THROW(EntityNotFound);

    Container<XmlNode> getNodes(const string &xpath) const;

    bool getBool(const string &xpath) const
    THROW(EntityNotFound);

    /**
     * \brief like getBool(xpath) but instead of throwing returns \arg defaultValue
     *
     *
     */
    bool getBool(const string &xpath, bool defaultValue) const;

    string getNodeName() const;

    XmlNode &operator=(const XmlNode &) = default;

    XmlNode &operator=(XmlNode &&) = default;
};

#include "NS-CLOSE"

#endif /* TOOLS_XALAN_XMLNODE_H_ */

инструменты/xalan/XmlNode.cpp

#include "XmlNode.h"

#include "XmlDoc.h"

#include "tools/llog/common.h"

#include "NS-OPEN"

XmlNode::XmlNode()
:   xalanXmlDoc(new XalanXmlDoc(std::string("<empty/>"))),
    node(xalanXmlDoc->getNode("/"))
{
    assert(this->node);
}

XmlNode::XmlNode(
    const std::shared_ptr<XalanXmlDoc> &xalanXmlDoc,
    const XalanXmlDoc::NodeHandle &node
    )
:   xalanXmlDoc(xalanXmlDoc),
    node(node)
{
    assert(this->node);
}

XmlDoc XmlNode::getDoc() const
{
    return XmlDoc(xalanXmlDoc);
}

auto XmlNode::getString(const string &xpath) const
THROW(EntityNotFound)
-> string
{
    assert(node);
    //may throw EntityNotFound
    return xalanXmlDoc->getString(node,xpath);
}

auto XmlNode::getString(const string &xpath, const string &defaultValue) const
-> string
{
    //may throw EntityNotFound
    return xalanXmlDoc->getString(node,xpath,defaultValue);
}

auto XmlNode::getStrings(const string &xpath) const
-> Container<string>
{
    return xalanXmlDoc->getStrings(node,xpath);
}

auto XmlNode::getNode(const string &xpath) const
THROW(EntityNotFound)
-> XmlNode
{
    BOOST_LOG_FUNCTION();
    //may throw EntityNotFound, NotUnique
    return XmlNode(xalanXmlDoc,xalanXmlDoc->getNode(node,xpath));
}

auto XmlNode::getNodes(const string &xpath) const
-> Container<XmlNode>
{
    using std::transform;
    auto xalanNodes = xalanXmlDoc->getNodes(node,xpath);
    Container<XmlNode> res;
    transform(
        xalanNodes.begin(), xalanNodes.end(),
        back_inserter(res),
        [this](const XalanXmlDoc::NodeHandle &xalanNode)->XmlNode
        {
            return XmlNode(this->xalanXmlDoc,xalanNode);
        }
        );
    return res;
}

auto XmlNode::getBool(const string &xpath) const
THROW(EntityNotFound)
-> bool
{
    //may throw EntityNotFound
    return xalanXmlDoc->getBool(node,xpath);
}

auto XmlNode::getBool(const string &xpath, bool defaultValue) const
-> bool
{
    return xalanXmlDoc->getBool(node,xpath,defaultValue);
}

auto XmlNode::getNodeName() const
-> string
{
    return xalanXmlDoc->getNodeName(node);
}
#include "NS-CLOSE"

XmlDoc.fwd.h

#ifndef TOOLS_XALAN_XMLDOC_FWD_H_
#define TOOLS_XALAN_XMLDOC_FWD_H_

#include "NS-OPEN"

class XmlDoc;

#include "NS-CLOSE"

#endif /* TOOLS_XALAN_XMLDOC_FWD_H_ */

XmlNode.fwd.h

#ifndef TOOLS_XALAN_XMLNODE_FWD_H_
#define TOOLS_XALAN_XMLNODE_FWD_H_

#include "NS-OPEN"

class XmlNode;

#include "NS-CLOSE"

#endif /* TOOLS_XALAN_XMLNODE_FWD_H_ */

XalanXmlDoc.h

#ifndef TOOLS_XALAN_XALANXMLDOC_H_
#define TOOLS_XALAN_XALANXMLDOC_H_

#include <string>
#include <boost/filesystem.hpp>
#include <mutex>
#include <vector>
#include <sstream>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xalanc/XalanDOM/XalanDocument.hpp>
#include <xalanc/XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
#include <xalanc/XalanSourceTree/XalanSourceTreeParserLiaison.hpp>
#include <xalanc/XPath/XPathEvaluator.hpp>
#include <xalanc/XSLT/XSLTInputSource.hpp>
#include "tools/exception/EntityNotFound.h"
#include "tools/exception/NotUnique.h"

#include "NS-OPEN"

/**
 * \brief XalanXmlDoc
 *
 * This is expected to be used through XmlDoc and XmlNode rather than directly.
 *
 * \see xalan/build/linux-64/xalan-c-1.11/c/samples/XPathWrapper/XPathWrapper.cpp
 *
 * \author David Laštovička
 */
class XalanXmlDoc {
protected:

    typedef std::string string;
    typedef boost::filesystem::path path;
    template<class T> using Container = std::vector<T>;
    typedef xercesc::XercesDOMParser XercesDOMParser;
    typedef xercesc::InputSource InputSource;
    typedef xalanc::XalanDocument XalanDocument;
    typedef xalanc::XalanSourceTreeDOMSupport XalanSourceTreeDOMSupport;
    typedef xalanc::XercesParserLiaison XercesParserLiaison;
    typedef xalanc::XalanSourceTreeParserLiaison XalanSourceTreeParserLiaison;
    typedef xalanc::XalanElement XalanElement;
    typedef xalanc::XalanNode XalanNode;
    typedef std::mutex mutex;
    typedef std::unique_lock<mutex> unique_lock;
    typedef tools::exception::EntityNotFound EntityNotFound;
    typedef tools::exception::NotUnique NotUnique;

public:
    typedef const XalanNode* NodeHandle;
private:

    /**
     * ToDo review Xalan/Xerces behaviour when called concurrently. Maybe the
     * mutex here is not necessary.
     */
    mutex accessMutex;

    mutable XalanSourceTreeDOMSupport domSupport;
    XalanSourceTreeParserLiaison parserLiaison;

    XalanDocument *xalanDoc;

public:

    /**
     * \brief This constructor instantiates the object.
     */
    XalanXmlDoc(const path &sourceFile);

    XalanXmlDoc(const string &xmlString);

    XalanXmlDoc(const XalanXmlDoc &) = delete;

    XalanXmlDoc(XalanXmlDoc &&) = delete;

    ~XalanXmlDoc();

    NodeHandle get_root() const;

    string getString(const string &xpath) const
    THROW(EntityNotFound);

    Container<string> getStrings(const string &xpath) const;

    NodeHandle getNode(const string &xpath) const
    THROW(EntityNotFound);

    Container<NodeHandle> getNodes(const string &xpath) const;

    string getString(const NodeHandle &xalanNode, const string &xpath) const
    THROW(EntityNotFound);

    string getString(const NodeHandle &xalanNode, const string &xpath, const string &defaultValue) const;

    Container<string> getStrings(const NodeHandle &xalanNode, const string &xpath) const;

    NodeHandle getNode(const NodeHandle &xalanNode, const string &xpath) const
    THROW(EntityNotFound);

    Container<NodeHandle> getNodes(
        const NodeHandle &xalanNode, const string &xpath
        ) const;

    /**
     * When more elements do match xpath so the first one is returned.
     * \throw EntityNotFound
     */
    bool getBool(const NodeHandle &xalanNode, const string &xpath) const
    THROW(EntityNotFound);

    /**
     * \brief like getBool(xalanNode, xpath) but instead of throwing EntityNotFound returns \arg defaultValue
     *
     */
    bool getBool(const NodeHandle &xalanNode, const string &xpath, bool defaultValue) const;

    string getNodeName(const NodeHandle &xalanNode) const;

};

#include "NS-CLOSE"

#endif /* TOOLS_XALAN_XALANXMLDOC_H_ */

XalanXmlDoc.cpp

#include "XalanXmlDoc.h"

#include <xercesc/sax/HandlerBase.hpp>
#include <xalanc/XPath/XPathEvaluator.hpp>
#include <xalanc/XPath/NodeRefList.hpp>
#include <xalanc/XalanDOM/XalanElement.hpp>
#include <xalanc/XalanDOM/XalanNamedNodeMap.hpp>
#include "tools/llog/common.h"
#include <sstream>
#include <vector>
#include "tools/text/ostream_iterator.h"
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include "tools/exception/Other.h"
#include "tools/exception/util/backtraceFactory.obj.h"
#include <xalanc/DOMSupport/XalanDocumentPrefixResolver.hpp>

#include "NS-OPEN"

static std::string toString(const xalanc::XalanDOMString &val)
{
    return std::string(val.begin(), val.end());
}

static void outputAttrs(std::ostream &oss, xalanc::XalanNode const * const node)
{
    using std::ostringstream;
    using xalanc::XalanNode;
    using xalanc::XalanElement;
    using xalanc::XalanSize_t;
    if (node->getNodeType()==XalanNode::ELEMENT_NODE) {
        XalanElement const * const element = static_cast<XalanElement const * const>(node);
        oss << "[";
        for (XalanSize_t i = 0; i<element->getAttributes()->getLength(); i++) {
            if (i>0) oss << ' ';
            oss << '@' << toString(element->getAttributes()->item(i)->getNodeName())
                << "='"
                << toString(element->getAttributes()->item(i)->getNodeValue())
                << "'";
        }
        oss << "]";
    }
}

static void outputFullPathWithAttrs(
    std::ostream &oss,
    xalanc::XalanNode const * const node,
    bool outputAttrsRequested
    )
{
    using std::ostringstream;
    using std::string;
    using std::vector;
    using tools::text::ostream_iterator;
    using std::copy;
    using xalanc::XalanNode;

    vector<string> nodeNames;
    {
        for(XalanNode const *it = node; it!=nullptr; it=it->getParentNode())
        {
            ostringstream oss;
            oss << toString(it->getNodeName());
            if (outputAttrsRequested)
                outputAttrs(oss, it);
            nodeNames.push_back(oss.str());
        }
    }

    copy(
        nodeNames.rbegin(), nodeNames.rend(),
        ostream_iterator<string>(oss,nullptr,nullptr,"/")
        );

}
/*
static std::string createFullPath(xalanc::XalanNode const * const node)
{
    using std::ostringstream;
    ostringstream oss;
    outputFullPathWithAttrs(oss,node,false);
    return oss.str();
}
*/
static std::string createFullPathWithAttrs(xalanc::XalanNode const * const node)
{
    using std::ostringstream;
    ostringstream oss;
    outputFullPathWithAttrs(oss,node,true);
    return oss.str();
}

XalanXmlDoc::XalanXmlDoc(const path &source)
:   //domSupport(parserLiaison),
    parserLiaison(domSupport)
{
    using xercesc::LocalFileInputSource;
    using xalanc::XalanDOMString;
    domSupport.setParserLiaison(&parserLiaison);
    const XalanDOMString    theFileName(source.native().c_str());
    LocalFileInputSource theInputSource(theFileName.c_str());
    xalanDoc = parserLiaison.parseXMLStream(theInputSource);
}

XalanXmlDoc::XalanXmlDoc(const string &xmlString)
:   //domSupport(parserLiaison),
    parserLiaison(domSupport)
{
    using xercesc::MemBufInputSource;
    using xalanc::XalanDOMString;
    domSupport.setParserLiaison(&parserLiaison);
    MemBufInputSource theInputSource(
        (const XMLByte *)xmlString.c_str(),
        xmlString.size(),
        "XalanXmlDoc"
        );
    xalanDoc = parserLiaison.parseXMLStream(theInputSource);
}

XalanXmlDoc::~XalanXmlDoc()
{
}

auto XalanXmlDoc::get_root() const
-> NodeHandle
{
    return xalanDoc;
}

auto XalanXmlDoc::getString(const string &xpath) const
THROW(EntityNotFound)
-> string
{
    //may throw EntityNotFound, NotUnique
    return getString(get_root(),xpath);
}

auto XalanXmlDoc::getStrings(const string &xpath) const
-> Container<string>
{
    return getStrings(get_root(),xpath);
}

auto XalanXmlDoc::getNode(const string &xpath) const
THROW(EntityNotFound)
-> NodeHandle
{
    //may throw EntityNotFound, NotUnique
    return getNode(get_root(), xpath);
}

auto XalanXmlDoc::getNodes(const string &xpath) const
-> Container<NodeHandle>
{
    return getNodes(get_root(), xpath);
}

auto XalanXmlDoc::getString(const NodeHandle &xalanNode, const string &xpath) const
THROW(EntityNotFound)
-> string
{
    //may throw EntityNotFound, NotUnique
    auto found = getNode(xalanNode, xpath);

    return toString(found->getNodeValue());
}

auto XalanXmlDoc::getString(const NodeHandle &xalanNode, const string &xpath, const string &defaultValue) const
-> string
{
    using exception::EntityNotFound;

    string res;
    try {
        //may throw EntityNotFound
        auto found = getNode(xalanNode, xpath);
        res = toString(found->getNodeValue());
    } catch (const EntityNotFound &e) {
        res = defaultValue;
    }
    return res;
}

auto XalanXmlDoc::getStrings(const NodeHandle &xalanNode, const string &xpath) const
-> Container<string>
{
    Container<string> res;
    for (auto node: getNodes(xalanNode, xpath))
    {
        res.push_back(toString(node->getNodeValue()));
    }
    return res;
}

auto XalanXmlDoc::getNode(const NodeHandle &xalanNode, const string &xpath) const
THROW(EntityNotFound)
-> NodeHandle
{
    BOOST_LOG_FUNCTION();

    using xalanc::XalanNode;
    using xalanc::XalanDOMString;
    using xalanc::XPathEvaluator;
    using std::ostringstream;
    using xercesc::SAXParseException;
    using xalanc::XalanDocumentPrefixResolver;

#ifndef NDEBUG
    if (!xalanNode) {
        BOOST_LOG_TRIVIAL(trace)
            << "Assertion failed evaluating " << xpath;
        BOOST_LOG_TRIVIAL(trace)
            << tools::exception::util::backtraceFactory().createBacktraces();
    }
    assert(xalanNode);

    {
        std::ostringstream oss;
        outputFullPathWithAttrs(oss,xalanNode,true);
        BOOST_LOG_TRIVIAL(trace)
            << "XalanXmlDoc::getNode " << xpath << " on type "
            << xalanNode->getNodeType()
            << " in " << oss.str();
    }
#endif
    //ToDo try can be removed the SAXParseException probably not thrown here but in the constructor
    try {
        XalanDocumentPrefixResolver thePrefixResolver(xalanDoc);
        const XalanDOMString expression(xpath.c_str());
        BOOST_LOG_TRIVIAL(trace) << "expression prepared";
        XPathEvaluator evaluator;

        //better use mutex when accessing the global domSupport etc.
        unique_lock(accessMutex);
        const XalanNode* found = evaluator.selectSingleNode(
            domSupport,
            const_cast<XalanNode *>(xalanNode),
            expression.c_str(),
            thePrefixResolver
            );

        if (!found) {
            ostringstream oss;
            oss << "Not found " << xpath << " on the node " << createFullPathWithAttrs(xalanNode);
            throw EntityNotFound(SRCINF, oss.str());
        }
        assert(found);
        BOOST_LOG_TRIVIAL(trace) << "returning node";
        return found;
    } catch (const SAXParseException &e) {
        using std::ostringstream;
        using exception::Other;
        ostringstream oss;
        oss << "SAXParseException line: " << e.getLineNumber() << " column: "
            << e.getColumnNumber() << " message: " << e.getMessage();
        throw Other(SRCINF,oss.str());
    }
}

auto XalanXmlDoc::getNodes(const NodeHandle &xalanNode, const string &xpath) const
-> Container<NodeHandle>
{
    using xalanc::XalanNode;
    using xalanc::XalanDOMString;
    using xalanc::XPathEvaluator;
    using xalanc::NodeRefList;
    using xercesc::SAXParseException;
    using xalanc::XalanDocumentPrefixResolver;

    BOOST_LOG_TRIVIAL(trace)
        << "XalanXmlDoc::getNodes " << xpath;

    //ToDo try can be removed the SAXParseException probably not thrown here but in the constructor
    try {
        XalanDocumentPrefixResolver thePrefixResolver(xalanDoc);
        const XalanDOMString expression(xpath.c_str());

        XPathEvaluator evaluator;

        NodeRefList foundNodes;

        {
            //better use mutex when accessing the global domSupport etc.
            unique_lock(accessMutex);

            evaluator.selectNodeList(
                foundNodes,
                domSupport,
                const_cast<XalanNode *>(xalanNode),
                expression.c_str(),
                thePrefixResolver
                );
        }
        std::vector<const XalanNode*> res;
        for (NodeRefList::size_type i=0;i<foundNodes.getLength();i++) {
            assert(foundNodes.item(i));
            res.push_back(foundNodes.item(i));
        }
        return res;
    } catch (const SAXParseException &e) {
        using std::ostringstream;
        using exception::Other;
        ostringstream oss;
        oss << "SAXParseException line: " << e.getLineNumber() << " column: "
            << e.getColumnNumber() << " message: " << e.getMessage();
        throw Other(SRCINF,oss.str());
    }
}
auto XalanXmlDoc::getBool(const NodeHandle &xalanNode, const string &xpath) const
THROW(EntityNotFound)
-> bool
{
    bool res;
    //may throw EntityNotFound, NotUnique
    std::istringstream(getString(xalanNode,xpath)) >> std::boolalpha >> res;
    return res;
}

auto XalanXmlDoc::getBool(const NodeHandle &xalanNode, const string &xpath, bool defaultValue) const
-> bool
{
    using exception::EntityNotFound;
    bool res;
    try {
        //may throw EntityNotFound, NotUnique
        res = getBool(xalanNode,xpath);
    } catch (const EntityNotFound &e) {
        res = defaultValue;
    }
    return res;
}

auto XalanXmlDoc::getNodeName(const NodeHandle &xalanNode) const
-> string
{
    assert(xalanNode);
    return toString(xalanNode->getNodeName());
}

#include "NS-CLOSE"
person David L.    schedule 19.04.2015