blob: c19535c29b4f918908d1650051309763e34e39b7 [file] [log] [blame]
#include <string>
#include <vector>
#include <cassert>
#include <iostream>
#include <parsers/DOMParser.hpp>
#include <util/PlatformUtils.hpp>
#include <dom/DOM_Node.hpp>
#include <dom/DOM_Document.hpp>
#include <dom/DOM_Element.hpp>
#include <dom/DOM_NodeList.hpp>
#include <framework/URLInputSource.hpp>
#include <PlatformSupport/DirectoryEnumerator.hpp>
#include <PlatformSupport/DOMStringHelper.hpp>
#include <DOMSupport/DOMSupportDefault.hpp>
#include <XPath/XObjectFactoryDefault.hpp>
#include <XPath/XPathEnvSupportDefault.hpp>
#include <XPath/XPathExecutionContextDefault.hpp>
#include <XPath/XPathSupportDefault.hpp>
#include <XPath/XPath.hpp>
#include <XPath/XPathProcessorImpl.hpp>
#include <XPath/XPathFactoryDefault.hpp>
#include <XPath/ElementPrefixResolverProxy.hpp>
#include <XMLSupport/FormatterTreeWalker.hpp>
#include <XMLSupport/FormatterToXML.hpp>
#include <XercesParserLiaison/XercesParserLiaison.hpp>
#include <framework/MemBufInputSource.hpp>
#include "XPathWrapper.hpp"
////////////////////////////////////////////////////
// the implementation class, that does all calls to XPath and Xerces
class XPathWrapperImpl
{
private:
std::string DOMStringToStdString(const DOMString& domString)
{
std::string ret;
for (int i=0; i< domString.length(); i++)
{
ret += (char)domString.charAt(i);
}
return ret;
}
public:
std::vector<std::string> evaluate(
const std::string& xml,
const std::string& context,
const std::string& expr)
{
//initialize XML4C
try
{
XMLPlatformUtils::Initialize();
}
catch(const XMLException& e)
{
throw;
}
// parse the XML file
DOM_Element rootNode;
DOMParser parser;
try
{
// parse XML and get root element
MemBufInputSource inStream((const XMLByte*)xml.c_str(),
xml.length(), "foo", false);
parser.parse(inStream);
DOM_Document doc = parser.getDocument();
rootNode = doc.getDocumentElement();
}
catch(const XMLException& e)
{
throw;
}
// configure the objects needed for XPath to work with the Xerces DOM
XPathEnvSupportDefault theEnvSupport;
DOMSupportDefault theDOMSupport;
XPathSupportDefault theSupport(theDOMSupport);
XObjectFactoryDefault theXObjectFactory(theEnvSupport, theSupport);
XPathExecutionContextDefault theExecutionContext(theEnvSupport, theSupport, theXObjectFactory);
XPathFactoryDefault theXPathFactory;
XPathProcessorImpl theXPathProcessor;
XercesParserLiaison theLiaison(theDOMSupport);
std::vector<std::string> theResultList;
try
{
// first get the context nodeset
XPath *contextXPath = theXPathFactory.create();
theXPathProcessor.initXPath(*contextXPath,
DOMString(context.c_str()),
ElementPrefixResolverProxy(rootNode,theSupport),
theXObjectFactory,
theEnvSupport);
MutableNodeRefList contextNodeList; //default empty context
XObject* xObj = contextXPath->execute(rootNode,
ElementPrefixResolverProxy(rootNode,theSupport),
contextNodeList,
theExecutionContext);
contextNodeList = xObj->mutableNodeset();
// and now get the result of the primary xpath expression
XPath *xpath = theXPathFactory.create();
theXPathProcessor.initXPath(*xpath,
DOMString(expr.c_str()),
ElementPrefixResolverProxy(rootNode, theSupport),
theXObjectFactory,
theEnvSupport);
xObj = xpath->execute(rootNode,
ElementPrefixResolverProxy(rootNode,theSupport),
contextNodeList,
theExecutionContext);
// now encode the results. For all types but nodelist, we'll just convert it to a string
// but, for nodelist, we'll convert each node to a string and return a list of them
switch (xObj->getType())
{
case XObject::eTypeNodeSet:
{
const NodeRefListBase& nodeset = xObj->nodeset();
size_t len = nodeset.getLength();
for (size_t i=0; i<len; i++)
{
DOM_Node node = nodeset.item(i);
DOMString str;
const int theType = node.getNodeType();
if (theType==DOM_Node::COMMENT_NODE || theType==DOM_Node::PROCESSING_INSTRUCTION_NODE)
str = node.getNodeValue();
else
str = theSupport.getNodeData(node);
theResultList.push_back(DOMStringToStdString(str));
}
break;
}
default:
{
theResultList.push_back(DOMStringToStdString(xObj->str()));
break;
}
}
}
catch(const XMLException& e)
{
throw;
}
return theResultList;
}
};
////////////////////////////////////////////////////
// The public XPathWrapper methods just delegate to our impl class
XPathWrapper::XPathWrapper()
{
pImpl = new XPathWrapperImpl();
}
XPathWrapper::~XPathWrapper()
{
delete pImpl;
}
std::vector<std::string> XPathWrapper::evaluate(
const std::string& xml,
const std::string& context,
const std::string& path)
{
return pImpl->evaluate(xml,context,path);
}