1e9cbe144SAndrew Rist /************************************************************** 2e9cbe144SAndrew Rist * 3e9cbe144SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4e9cbe144SAndrew Rist * or more contributor license agreements. See the NOTICE file 5e9cbe144SAndrew Rist * distributed with this work for additional information 6e9cbe144SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7e9cbe144SAndrew Rist * to you under the Apache License, Version 2.0 (the 8e9cbe144SAndrew Rist * "License"); you may not use this file except in compliance 9e9cbe144SAndrew Rist * with the License. You may obtain a copy of the License at 10e9cbe144SAndrew Rist * 11e9cbe144SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12e9cbe144SAndrew Rist * 13e9cbe144SAndrew Rist * Unless required by applicable law or agreed to in writing, 14e9cbe144SAndrew Rist * software distributed under the License is distributed on an 15e9cbe144SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16e9cbe144SAndrew Rist * KIND, either express or implied. See the License for the 17e9cbe144SAndrew Rist * specific language governing permissions and limitations 18e9cbe144SAndrew Rist * under the License. 19e9cbe144SAndrew Rist * 20e9cbe144SAndrew Rist *************************************************************/ 21e9cbe144SAndrew Rist 22e9cbe144SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include <xpathapi.hxx> 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <stdarg.h> 27cdf0e10cSrcweir #include <string.h> 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include <libxml/tree.h> 30cdf0e10cSrcweir #include <libxml/xmlerror.h> 31cdf0e10cSrcweir #include <libxml/xpath.h> 32cdf0e10cSrcweir #include <libxml/xpathInternals.h> 33cdf0e10cSrcweir 34cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 35cdf0e10cSrcweir 36cdf0e10cSrcweir #include <nodelist.hxx> 37cdf0e10cSrcweir #include <xpathobject.hxx> 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include "../dom/node.hxx" 40cdf0e10cSrcweir #include "../dom/document.hxx" 41cdf0e10cSrcweir 42cdf0e10cSrcweir 43cdf0e10cSrcweir using ::com::sun::star::lang::XMultiServiceFactory; 44cdf0e10cSrcweir 45cdf0e10cSrcweir 46cdf0e10cSrcweir namespace XPath 47cdf0e10cSrcweir { 48cdf0e10cSrcweir // factory _getInstance(const Reference<XMultiServiceFactory> & rSMgr)49cdf0e10cSrcweir Reference< XInterface > CXPathAPI::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) 50cdf0e10cSrcweir { 51cdf0e10cSrcweir return Reference< XInterface >(static_cast<XXPathAPI*>(new CXPathAPI(rSMgr))); 52cdf0e10cSrcweir } 53cdf0e10cSrcweir 54cdf0e10cSrcweir // ctor CXPathAPI(const Reference<XMultiServiceFactory> & rSMgr)55cdf0e10cSrcweir CXPathAPI::CXPathAPI(const Reference< XMultiServiceFactory >& rSMgr) 56cdf0e10cSrcweir : m_aFactory(rSMgr) 57cdf0e10cSrcweir { 58cdf0e10cSrcweir } 59cdf0e10cSrcweir 60cdf0e10cSrcweir const char* CXPathAPI::aImplementationName = "com.sun.star.comp.xml.xpath.XPathAPI"; 61cdf0e10cSrcweir const char* CXPathAPI::aSupportedServiceNames[] = { 62cdf0e10cSrcweir "com.sun.star.xml.xpath.XPathAPI", 63cdf0e10cSrcweir NULL 64cdf0e10cSrcweir }; 65cdf0e10cSrcweir _getImplementationName()66cdf0e10cSrcweir OUString CXPathAPI::_getImplementationName() 67cdf0e10cSrcweir { 68cdf0e10cSrcweir return OUString::createFromAscii(aImplementationName); 69cdf0e10cSrcweir } 70cdf0e10cSrcweir _getSupportedServiceNames()71cdf0e10cSrcweir Sequence<OUString> CXPathAPI::_getSupportedServiceNames() 72cdf0e10cSrcweir { 73cdf0e10cSrcweir Sequence<OUString> aSequence; 74cdf0e10cSrcweir for (int i=0; aSupportedServiceNames[i]!=NULL; i++) { 75cdf0e10cSrcweir aSequence.realloc(i+1); 76cdf0e10cSrcweir aSequence[i]=(OUString::createFromAscii(aSupportedServiceNames[i])); 77cdf0e10cSrcweir } 78cdf0e10cSrcweir return aSequence; 79cdf0e10cSrcweir } 80cdf0e10cSrcweir getSupportedServiceNames()81cdf0e10cSrcweir Sequence< OUString > SAL_CALL CXPathAPI::getSupportedServiceNames() 82cdf0e10cSrcweir throw (RuntimeException) 83cdf0e10cSrcweir { 84cdf0e10cSrcweir return CXPathAPI::_getSupportedServiceNames(); 85cdf0e10cSrcweir } 86cdf0e10cSrcweir getImplementationName()87cdf0e10cSrcweir OUString SAL_CALL CXPathAPI::getImplementationName() 88cdf0e10cSrcweir throw (RuntimeException) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir return CXPathAPI::_getImplementationName(); 91cdf0e10cSrcweir } 92cdf0e10cSrcweir supportsService(const OUString & aServiceName)93cdf0e10cSrcweir sal_Bool SAL_CALL CXPathAPI::supportsService(const OUString& aServiceName) 94cdf0e10cSrcweir throw (RuntimeException) 95cdf0e10cSrcweir { 96cdf0e10cSrcweir Sequence< OUString > supported = CXPathAPI::_getSupportedServiceNames(); 97cdf0e10cSrcweir for (sal_Int32 i=0; i<supported.getLength(); i++) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir if (supported[i] == aServiceName) return sal_True; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir return sal_False; 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir // ------------------------------------------------------------------- 105cdf0e10cSrcweir registerNS(const OUString & aPrefix,const OUString & aURI)106cdf0e10cSrcweir void SAL_CALL CXPathAPI::registerNS( 107cdf0e10cSrcweir const OUString& aPrefix, 108cdf0e10cSrcweir const OUString& aURI) 109cdf0e10cSrcweir throw (RuntimeException) 110cdf0e10cSrcweir { 111cdf0e10cSrcweir ::osl::MutexGuard const g(m_Mutex); 112cdf0e10cSrcweir 113cdf0e10cSrcweir m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI)); 114cdf0e10cSrcweir } 115cdf0e10cSrcweir unregisterNS(const OUString & aPrefix,const OUString & aURI)116cdf0e10cSrcweir void SAL_CALL CXPathAPI::unregisterNS( 117cdf0e10cSrcweir const OUString& aPrefix, 118cdf0e10cSrcweir const OUString& aURI) 119cdf0e10cSrcweir throw (RuntimeException) 120cdf0e10cSrcweir { 121cdf0e10cSrcweir ::osl::MutexGuard const g(m_Mutex); 122cdf0e10cSrcweir 123cdf0e10cSrcweir if ((m_nsmap.find(aPrefix))->second.equals(aURI)) { 124cdf0e10cSrcweir m_nsmap.erase(aPrefix); 125cdf0e10cSrcweir } 126cdf0e10cSrcweir } 127cdf0e10cSrcweir 128cdf0e10cSrcweir // register all namespaces stored in the namespace list for this object 129cdf0e10cSrcweir // with the current xpath evaluation context lcl_registerNamespaces(xmlXPathContextPtr ctx,const nsmap_t & nsmap)130cdf0e10cSrcweir static void lcl_registerNamespaces( 131cdf0e10cSrcweir xmlXPathContextPtr ctx, 132cdf0e10cSrcweir const nsmap_t& nsmap) 133cdf0e10cSrcweir { 134cdf0e10cSrcweir nsmap_t::const_iterator i = nsmap.begin(); 135cdf0e10cSrcweir OString oprefix, ouri; 136cdf0e10cSrcweir xmlChar *p, *u; 137cdf0e10cSrcweir while (i != nsmap.end()) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir oprefix = OUStringToOString(i->first, RTL_TEXTENCODING_UTF8); 140cdf0e10cSrcweir ouri = OUStringToOString(i->second, RTL_TEXTENCODING_UTF8); 141cdf0e10cSrcweir p = (xmlChar*)oprefix.getStr(); 142cdf0e10cSrcweir u = (xmlChar*)ouri.getStr(); 143cdf0e10cSrcweir xmlXPathRegisterNs(ctx, p, u); 144cdf0e10cSrcweir i++; 145cdf0e10cSrcweir } 146cdf0e10cSrcweir } 147cdf0e10cSrcweir 148cdf0e10cSrcweir // get all ns decls on a node (and parent nodes, if any) lcl_collectNamespaces(nsmap_t & rNamespaces,Reference<XNode> const & xNamespaceNode)149cdf0e10cSrcweir static void lcl_collectNamespaces( 150cdf0e10cSrcweir nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir DOM::CNode *const pCNode(DOM::CNode::GetImplementation(xNamespaceNode)); 153cdf0e10cSrcweir if (!pCNode) { throw RuntimeException(); } 154cdf0e10cSrcweir 155cdf0e10cSrcweir ::osl::MutexGuard const g(pCNode->GetOwnerDocument().GetMutex()); 156cdf0e10cSrcweir 157cdf0e10cSrcweir xmlNodePtr pNode = pCNode->GetNodePtr(); 158cdf0e10cSrcweir while (pNode != 0) { 159cdf0e10cSrcweir xmlNsPtr curDef = pNode->nsDef; 160cdf0e10cSrcweir while (curDef != 0) { 161cdf0e10cSrcweir const xmlChar* xHref = curDef->href; 162cdf0e10cSrcweir OUString aURI((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); 163cdf0e10cSrcweir const xmlChar* xPre = curDef->prefix; 164cdf0e10cSrcweir OUString aPrefix((sal_Char*)xPre, strlen((char*)xPre), RTL_TEXTENCODING_UTF8); 165cdf0e10cSrcweir // we could already have this prefix from a child node 166cdf0e10cSrcweir if (rNamespaces.find(aPrefix) == rNamespaces.end()) 167cdf0e10cSrcweir { 168cdf0e10cSrcweir rNamespaces.insert(::std::make_pair(aPrefix, aURI)); 169cdf0e10cSrcweir } 170cdf0e10cSrcweir curDef = curDef->next; 171cdf0e10cSrcweir } 172cdf0e10cSrcweir pNode = pNode->parent; 173cdf0e10cSrcweir } 174cdf0e10cSrcweir } 175cdf0e10cSrcweir lcl_collectRegisterNamespaces(CXPathAPI & rAPI,Reference<XNode> const & xNamespaceNode)176cdf0e10cSrcweir static void lcl_collectRegisterNamespaces( 177cdf0e10cSrcweir CXPathAPI & rAPI, Reference< XNode > const& xNamespaceNode) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir nsmap_t namespaces; 180cdf0e10cSrcweir lcl_collectNamespaces(namespaces, xNamespaceNode); 181cdf0e10cSrcweir for (nsmap_t::const_iterator iter = namespaces.begin(); 182cdf0e10cSrcweir iter != namespaces.end(); ++iter) 183cdf0e10cSrcweir { 184cdf0e10cSrcweir rAPI.registerNS(iter->first, iter->second); 185cdf0e10cSrcweir } 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir // register function and variable lookup functions with the current 189cdf0e10cSrcweir // xpath evaluation context lcl_registerExtensions(xmlXPathContextPtr ctx,const extensions_t & extensions)190cdf0e10cSrcweir static void lcl_registerExtensions( 191cdf0e10cSrcweir xmlXPathContextPtr ctx, 192cdf0e10cSrcweir const extensions_t& extensions) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir extensions_t::const_iterator i = extensions.begin(); 195cdf0e10cSrcweir while (i != extensions.end()) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir Libxml2ExtensionHandle aHandle = (*i)->getLibxml2ExtensionHandle(); 198cdf0e10cSrcweir if ( aHandle.functionLookupFunction != 0 ) 199cdf0e10cSrcweir { 200cdf0e10cSrcweir xmlXPathRegisterFuncLookup(ctx, 201cdf0e10cSrcweir reinterpret_cast<xmlXPathFuncLookupFunc>( 202cdf0e10cSrcweir sal::static_int_cast<sal_IntPtr>(aHandle.functionLookupFunction)), 203cdf0e10cSrcweir reinterpret_cast<void*>( 204cdf0e10cSrcweir sal::static_int_cast<sal_IntPtr>(aHandle.functionData))); 205cdf0e10cSrcweir } 206cdf0e10cSrcweir if ( aHandle.variableLookupFunction != 0 ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir xmlXPathRegisterVariableLookup(ctx, 209cdf0e10cSrcweir reinterpret_cast<xmlXPathVariableLookupFunc>( 210cdf0e10cSrcweir sal::static_int_cast<sal_IntPtr>(aHandle.variableLookupFunction)), 211cdf0e10cSrcweir reinterpret_cast<void*>( 212cdf0e10cSrcweir sal::static_int_cast<sal_IntPtr>(aHandle.variableData))); 213cdf0e10cSrcweir } 214cdf0e10cSrcweir i++; 215cdf0e10cSrcweir } 216cdf0e10cSrcweir } 217cdf0e10cSrcweir 218cdf0e10cSrcweir /** 219cdf0e10cSrcweir * Use an XPath string to select a nodelist. 220cdf0e10cSrcweir */ selectNodeList(const Reference<XNode> & contextNode,const OUString & expr)221cdf0e10cSrcweir Reference< XNodeList > SAL_CALL CXPathAPI::selectNodeList( 222cdf0e10cSrcweir const Reference< XNode >& contextNode, 223cdf0e10cSrcweir const OUString& expr) 224cdf0e10cSrcweir throw (RuntimeException, XPathException) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir Reference< XXPathObject > xobj = eval(contextNode, expr); 227cdf0e10cSrcweir return xobj->getNodeList(); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir /** 231cdf0e10cSrcweir * same as selectNodeList but registers all name space decalratiosn found on namespaceNode 232cdf0e10cSrcweir */ selectNodeListNS(const Reference<XNode> & contextNode,const OUString & expr,const Reference<XNode> & namespaceNode)233cdf0e10cSrcweir Reference< XNodeList > SAL_CALL CXPathAPI::selectNodeListNS( 234cdf0e10cSrcweir const Reference< XNode >& contextNode, 235cdf0e10cSrcweir const OUString& expr, 236cdf0e10cSrcweir const Reference< XNode >& namespaceNode) 237cdf0e10cSrcweir throw (RuntimeException, XPathException) 238cdf0e10cSrcweir { 239cdf0e10cSrcweir lcl_collectRegisterNamespaces(*this, namespaceNode); 240cdf0e10cSrcweir return selectNodeList(contextNode, expr); 241cdf0e10cSrcweir } 242cdf0e10cSrcweir 243cdf0e10cSrcweir /** 244cdf0e10cSrcweir * Same as selectNodeList but returns the first node (if any) 245cdf0e10cSrcweir */ selectSingleNode(const Reference<XNode> & contextNode,const OUString & expr)246cdf0e10cSrcweir Reference< XNode > SAL_CALL CXPathAPI::selectSingleNode( 247cdf0e10cSrcweir const Reference< XNode >& contextNode, 248cdf0e10cSrcweir const OUString& expr) 249cdf0e10cSrcweir throw (RuntimeException, XPathException) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir Reference< XNodeList > aList = selectNodeList(contextNode, expr); 252cdf0e10cSrcweir Reference< XNode > aNode = aList->item(0); 253cdf0e10cSrcweir return aNode; 254cdf0e10cSrcweir } 255cdf0e10cSrcweir 256cdf0e10cSrcweir /** 257cdf0e10cSrcweir * Same as selectSingleNode but registers all namespaces declared on 258cdf0e10cSrcweir * namespaceNode 259cdf0e10cSrcweir */ selectSingleNodeNS(const Reference<XNode> & contextNode,const OUString & expr,const Reference<XNode> & namespaceNode)260cdf0e10cSrcweir Reference< XNode > SAL_CALL CXPathAPI::selectSingleNodeNS( 261cdf0e10cSrcweir const Reference< XNode >& contextNode, 262cdf0e10cSrcweir const OUString& expr, 263cdf0e10cSrcweir const Reference< XNode >& namespaceNode ) 264cdf0e10cSrcweir throw (RuntimeException, XPathException) 265cdf0e10cSrcweir { 266cdf0e10cSrcweir lcl_collectRegisterNamespaces(*this, namespaceNode); 267cdf0e10cSrcweir return selectSingleNode(contextNode, expr); 268cdf0e10cSrcweir } 269cdf0e10cSrcweir make_error_message(xmlErrorPtr pError)270cdf0e10cSrcweir static OUString make_error_message(xmlErrorPtr pError) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir ::rtl::OUStringBuffer buf; 273cdf0e10cSrcweir if (pError->message) { 274cdf0e10cSrcweir buf.appendAscii(pError->message); 275cdf0e10cSrcweir } 276cdf0e10cSrcweir int line = pError->line; 277cdf0e10cSrcweir if (line) { 278cdf0e10cSrcweir buf.appendAscii("Line: "); 279cdf0e10cSrcweir buf.append(static_cast<sal_Int32>(line)); 280cdf0e10cSrcweir buf.appendAscii("\n"); 281cdf0e10cSrcweir } 282cdf0e10cSrcweir int column = pError->int2; 283cdf0e10cSrcweir if (column) { 284cdf0e10cSrcweir buf.appendAscii("Column: "); 285cdf0e10cSrcweir buf.append(static_cast<sal_Int32>(column)); 286cdf0e10cSrcweir buf.appendAscii("\n"); 287cdf0e10cSrcweir } 288cdf0e10cSrcweir OUString msg = buf.makeStringAndClear(); 289cdf0e10cSrcweir return msg; 290cdf0e10cSrcweir } 291cdf0e10cSrcweir 292cdf0e10cSrcweir extern "C" { 293cdf0e10cSrcweir generic_error_func(void * userData,const char * format,...)294cdf0e10cSrcweir static void generic_error_func(void *userData, const char *format, ...) 295cdf0e10cSrcweir { 296cdf0e10cSrcweir (void) userData; 297cdf0e10cSrcweir char str[1000]; 298cdf0e10cSrcweir va_list args; 299cdf0e10cSrcweir 300cdf0e10cSrcweir va_start(args, format); 301cdf0e10cSrcweir #ifdef _WIN32 302cdf0e10cSrcweir #define vsnprintf _vsnprintf 303cdf0e10cSrcweir #endif 304cdf0e10cSrcweir vsnprintf(str, sizeof(str), format, args); 305cdf0e10cSrcweir va_end(args); 306cdf0e10cSrcweir 307cdf0e10cSrcweir ::rtl::OUStringBuffer buf( 308cdf0e10cSrcweir OUString::createFromAscii("libxml2 error:\n")); 309cdf0e10cSrcweir buf.appendAscii(str); 310cdf0e10cSrcweir OString msg = OUStringToOString(buf.makeStringAndClear(), 311cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 312cdf0e10cSrcweir OSL_ENSURE(sal_False, msg.getStr()); 313cdf0e10cSrcweir } 314cdf0e10cSrcweir structured_error_func(void * userData,xmlErrorPtr error)315cdf0e10cSrcweir static void structured_error_func(void * userData, xmlErrorPtr error) 316cdf0e10cSrcweir { 317cdf0e10cSrcweir (void) userData; 318cdf0e10cSrcweir ::rtl::OUStringBuffer buf( 319cdf0e10cSrcweir OUString::createFromAscii("libxml2 error:\n")); 320cdf0e10cSrcweir if (error) { 321cdf0e10cSrcweir buf.append(make_error_message(error)); 322cdf0e10cSrcweir } else { 323cdf0e10cSrcweir buf.append(OUString::createFromAscii("no error argument!")); 324cdf0e10cSrcweir } 325cdf0e10cSrcweir OString msg = OUStringToOString(buf.makeStringAndClear(), 326cdf0e10cSrcweir RTL_TEXTENCODING_ASCII_US); 327cdf0e10cSrcweir OSL_ENSURE(sal_False, msg.getStr()); 328cdf0e10cSrcweir } 329cdf0e10cSrcweir 330cdf0e10cSrcweir } // extern "C" 331cdf0e10cSrcweir 332cdf0e10cSrcweir /** 333cdf0e10cSrcweir * evaluates an XPath string. relative XPath expressions are evaluated relative to 334cdf0e10cSrcweir * the context Node 335cdf0e10cSrcweir */ eval(Reference<XNode> const & xContextNode,const OUString & expr)336cdf0e10cSrcweir Reference< XXPathObject > SAL_CALL CXPathAPI::eval( 337cdf0e10cSrcweir Reference< XNode > const& xContextNode, 338cdf0e10cSrcweir const OUString& expr) 339cdf0e10cSrcweir throw (RuntimeException, XPathException) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir if (!xContextNode.is()) { throw RuntimeException(); } 342cdf0e10cSrcweir 343cdf0e10cSrcweir nsmap_t nsmap; 344cdf0e10cSrcweir extensions_t extensions; 345cdf0e10cSrcweir 346cdf0e10cSrcweir { 347cdf0e10cSrcweir ::osl::MutexGuard const g(m_Mutex); 348cdf0e10cSrcweir nsmap = m_nsmap; 349cdf0e10cSrcweir extensions = m_extensions; 350cdf0e10cSrcweir } 351cdf0e10cSrcweir 352cdf0e10cSrcweir // get the node and document 353cdf0e10cSrcweir ::rtl::Reference<DOM::CDocument> const pCDoc( 354cdf0e10cSrcweir dynamic_cast<DOM::CDocument*>( DOM::CNode::GetImplementation( 355cdf0e10cSrcweir xContextNode->getOwnerDocument()))); 356cdf0e10cSrcweir if (!pCDoc.is()) { throw RuntimeException(); } 357cdf0e10cSrcweir 358cdf0e10cSrcweir DOM::CNode *const pCNode = DOM::CNode::GetImplementation(xContextNode); 359cdf0e10cSrcweir if (!pCNode) { throw RuntimeException(); } 360cdf0e10cSrcweir 361cdf0e10cSrcweir ::osl::MutexGuard const g(pCDoc->GetMutex()); // lock the document! 362cdf0e10cSrcweir 363cdf0e10cSrcweir xmlNodePtr const pNode = pCNode->GetNodePtr(); 364cdf0e10cSrcweir if (!pNode) { throw RuntimeException(); } 365cdf0e10cSrcweir xmlDocPtr pDoc = pNode->doc; 366cdf0e10cSrcweir 367cdf0e10cSrcweir /* NB: workaround for #i87252#: 368cdf0e10cSrcweir libxml < 2.6.17 considers it an error if the context 369cdf0e10cSrcweir node is the empty document (i.e. its xpathCtx->doc has no 370cdf0e10cSrcweir children). libxml 2.6.17 does not consider it an error. 371cdf0e10cSrcweir Unfortunately, old libxml prints an error message to stderr, 372cdf0e10cSrcweir which (afaik) cannot be turned off in this case, so we handle it. 373cdf0e10cSrcweir */ 374cdf0e10cSrcweir if (!pDoc->children) { 375cdf0e10cSrcweir throw XPathException(); 376cdf0e10cSrcweir } 377cdf0e10cSrcweir 378cdf0e10cSrcweir /* Create xpath evaluation context */ 379cdf0e10cSrcweir ::boost::shared_ptr<xmlXPathContext> const xpathCtx( 380cdf0e10cSrcweir xmlXPathNewContext(pDoc), xmlXPathFreeContext); 381*b862c97cSHerbert Dürr if( !bool(xpathCtx)) { throw XPathException(); } 382cdf0e10cSrcweir 383cdf0e10cSrcweir // set context node 384cdf0e10cSrcweir xpathCtx->node = pNode; 385cdf0e10cSrcweir // error handling 386cdf0e10cSrcweir xpathCtx->error = structured_error_func; 387cdf0e10cSrcweir xmlSetGenericErrorFunc(NULL, generic_error_func); 388cdf0e10cSrcweir 389cdf0e10cSrcweir // register namespaces and extension 390cdf0e10cSrcweir lcl_registerNamespaces(xpathCtx.get(), nsmap); 391cdf0e10cSrcweir lcl_registerExtensions(xpathCtx.get(), extensions); 392cdf0e10cSrcweir 393cdf0e10cSrcweir /* run the query */ 394cdf0e10cSrcweir OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8); 395cdf0e10cSrcweir xmlChar *xStr = (xmlChar*)o1.getStr(); 396cdf0e10cSrcweir ::boost::shared_ptr<xmlXPathObject> const xpathObj( 397cdf0e10cSrcweir xmlXPathEval(xStr, xpathCtx.get()), xmlXPathFreeObject); 398cdf0e10cSrcweir if (0 == xpathObj) { 399cdf0e10cSrcweir // OSL_ENSURE(xpathCtx->lastError == NULL, xpathCtx->lastError->message); 400cdf0e10cSrcweir throw XPathException(); 401cdf0e10cSrcweir } 402cdf0e10cSrcweir Reference<XXPathObject> const xObj( 403cdf0e10cSrcweir new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj)); 404cdf0e10cSrcweir return xObj; 405cdf0e10cSrcweir } 406cdf0e10cSrcweir 407cdf0e10cSrcweir /** 408cdf0e10cSrcweir * same as eval but registers all namespace declarations found on namespaceNode 409cdf0e10cSrcweir */ evalNS(const Reference<XNode> & contextNode,const OUString & expr,const Reference<XNode> & namespaceNode)410cdf0e10cSrcweir Reference< XXPathObject > SAL_CALL CXPathAPI::evalNS( 411cdf0e10cSrcweir const Reference< XNode >& contextNode, 412cdf0e10cSrcweir const OUString& expr, 413cdf0e10cSrcweir const Reference< XNode >& namespaceNode) 414cdf0e10cSrcweir throw (RuntimeException, XPathException) 415cdf0e10cSrcweir { 416cdf0e10cSrcweir lcl_collectRegisterNamespaces(*this, namespaceNode); 417cdf0e10cSrcweir return eval(contextNode, expr); 418cdf0e10cSrcweir } 419cdf0e10cSrcweir 420cdf0e10cSrcweir /** 421cdf0e10cSrcweir * uses the service manager to create an instance of the service denoted by aName. 422cdf0e10cSrcweir * If the returned object implements the XXPathExtension interface, it is added to the list 423cdf0e10cSrcweir * of extensions that are used when evaluating XPath strings with this XPathAPI instance 424cdf0e10cSrcweir */ registerExtension(const OUString & aName)425cdf0e10cSrcweir void SAL_CALL CXPathAPI::registerExtension( 426cdf0e10cSrcweir const OUString& aName) 427cdf0e10cSrcweir throw (RuntimeException) 428cdf0e10cSrcweir { 429cdf0e10cSrcweir ::osl::MutexGuard const g(m_Mutex); 430cdf0e10cSrcweir 431cdf0e10cSrcweir // get extension from service manager 432cdf0e10cSrcweir Reference< XXPathExtension > const xExtension( 433cdf0e10cSrcweir m_aFactory->createInstance(aName), UNO_QUERY_THROW); 434cdf0e10cSrcweir m_extensions.push_back(xExtension); 435cdf0e10cSrcweir } 436cdf0e10cSrcweir 437cdf0e10cSrcweir /** 438cdf0e10cSrcweir * registers the given extension instance to be used by XPath evaluations performed through this 439cdf0e10cSrcweir * XPathAPI instance 440cdf0e10cSrcweir */ registerExtensionInstance(Reference<XXPathExtension> const & xExtension)441cdf0e10cSrcweir void SAL_CALL CXPathAPI::registerExtensionInstance( 442cdf0e10cSrcweir Reference< XXPathExtension> const& xExtension) 443cdf0e10cSrcweir throw (RuntimeException) 444cdf0e10cSrcweir { 445cdf0e10cSrcweir if (!xExtension.is()) { 446cdf0e10cSrcweir throw RuntimeException(); 447cdf0e10cSrcweir } 448cdf0e10cSrcweir ::osl::MutexGuard const g(m_Mutex); 449cdf0e10cSrcweir m_extensions.push_back( xExtension ); 450cdf0e10cSrcweir } 451cdf0e10cSrcweir } 452