25#include <libxml/tree.h>
26#include <libxml/xmlerror.h>
27#include <libxml/xpath.h>
28#include <libxml/xpathInternals.h>
30#include <com/sun/star/xml/xpath/XPathException.hpp>
32#include <rtl/ustrbuf.hxx>
38#include "../dom/document.hxx"
43using namespace css::io;
44using namespace css::uno;
45using namespace css::xml::dom;
46using namespace css::xml::xpath;
58 return {
"com.sun.star.xml.xpath.XPathAPI" };
63 return "com.sun.star.comp.xml.xpath.XPathAPI";
72 const OUString& aPrefix,
75 std::scoped_lock
const g(
m_Mutex);
81 const OUString& aPrefix,
84 std::scoped_lock
const g(
m_Mutex);
86 if ((
m_nsmap.find(aPrefix))->second == aURI) {
94 xmlXPathContextPtr ctx,
97 OString oprefix, ouri;
98 for (
const auto& rEntry : nsmap)
102 xmlChar
const *
p =
reinterpret_cast<xmlChar
const *
>(oprefix.getStr());
103 xmlChar
const *
u =
reinterpret_cast<xmlChar
const *
>(ouri.getStr());
104 (void)xmlXPathRegisterNs(
ctx,
p,
u);
110 nsmap_t & rNamespaces, Reference< XNode >
const& xNamespaceNode)
112 DOM::CNode *
const pCNode(
dynamic_cast<DOM::CNode*
>(xNamespaceNode.get()));
115 ::osl::MutexGuard
const g(pCNode->GetOwnerDocument().GetMutex());
117 xmlNodePtr pNode = pCNode->GetNodePtr();
118 while (pNode !=
nullptr) {
119 xmlNsPtr curDef = pNode->nsDef;
120 while (curDef !=
nullptr) {
121 const xmlChar* pHref = curDef->href;
122 OUString aURI(
reinterpret_cast<char const *
>(pHref), strlen(
reinterpret_cast<char const *
>(pHref)), RTL_TEXTENCODING_UTF8);
123 const xmlChar* pPre = curDef->prefix;
124 OUString aPrefix(
reinterpret_cast<char const *
>(pPre), strlen(
reinterpret_cast<char const *
>(pPre)), RTL_TEXTENCODING_UTF8);
126 rNamespaces.emplace(aPrefix, aURI);
127 curDef = curDef->next;
129 pNode = pNode->parent;
134 CXPathAPI & rAPI, Reference< XNode >
const& xNamespaceNode)
147 xmlXPathContextPtr ctx,
152 Libxml2ExtensionHandle aHandle = rExtensionRef->getLibxml2ExtensionHandle();
153 if ( aHandle.functionLookupFunction != 0 )
155 xmlXPathRegisterFuncLookup(
ctx,
156 reinterpret_cast<xmlXPathFuncLookupFunc
>(
157 sal::static_int_cast<sal_IntPtr>(aHandle.functionLookupFunction)),
158 reinterpret_cast<void*
>(
159 sal::static_int_cast<sal_IntPtr>(aHandle.functionData)));
161 if ( aHandle.variableLookupFunction != 0 )
163 xmlXPathRegisterVariableLookup(
ctx,
164 reinterpret_cast<xmlXPathVariableLookupFunc
>(
165 sal::static_int_cast<sal_IntPtr>(aHandle.variableLookupFunction)),
166 reinterpret_cast<void*
>(
167 sal::static_int_cast<sal_IntPtr>(aHandle.variableData)));
176 const Reference< XNode >& contextNode,
177 const OUString& expr)
179 Reference< XXPathObject > xobj =
eval(contextNode, expr);
180 return xobj->getNodeList();
187 const Reference< XNode >& contextNode,
188 const OUString& expr,
189 const Reference< XNode >& namespaceNode)
199 const Reference< XNode >& contextNode,
200 const OUString& expr)
203 Reference< XNode > aNode = aList->item(0);
212 const Reference< XNode >& contextNode,
213 const OUString& expr,
214 const Reference< XNode >& namespaceNode )
224 if (pError->message) {
225 buf.appendAscii(pError->message);
227 int line = pError->line;
229 buf.append(
"Line: " + OUString::number(
static_cast<sal_Int32
>(
line)) +
"\n");
231 int column = pError->int2;
233 buf.append(
"Column: " + OUString::number(
static_cast<sal_Int32
>(column)) +
"\n");
236 buf.append(
"no error argument!");
238 OUString msg = buf.makeStringAndClear();
252 va_start(
args, format);
254#define vsnprintf _vsnprintf
256 vsnprintf(str,
sizeof(str), format,
args);
259 SAL_WARN(
"unoxml",
"libxml2 error: " << str);
274 Reference< XNode >
const& xContextNode,
275 const OUString& expr)
283 std::scoped_lock
const g(
m_Mutex);
290 dynamic_cast<DOM::CDocument*
>(xContextNode->getOwnerDocument().get()));
293 DOM::CNode *
const pCNode =
dynamic_cast<DOM::CNode*
>(xContextNode.get());
296 ::osl::MutexGuard
const g(pCDoc->GetMutex());
298 xmlNodePtr
const pNode = pCNode->GetNodePtr();
300 xmlDocPtr pDoc = pNode->doc;
309 if (!pDoc->children) {
310 throw XPathException();
314 std::shared_ptr<xmlXPathContext>
const xpathCtx(
315 xmlXPathNewContext(pDoc), xmlXPathFreeContext);
316 if (xpathCtx ==
nullptr) {
throw XPathException(); }
319 xpathCtx->node = pNode;
330 xmlChar
const *pStr =
reinterpret_cast<xmlChar
const *
>(o1.getStr());
331 std::shared_ptr<xmlXPathObject>
const xpathObj(
332 xmlXPathEval(pStr, xpathCtx.get()), xmlXPathFreeObject);
333 xmlSetGenericErrorFunc(
nullptr,
nullptr);
334 if (
nullptr == xpathObj) {
336 throw XPathException();
338 Reference<XXPathObject>
const xObj(
347 const Reference< XNode >& contextNode,
348 const OUString& expr,
349 const Reference< XNode >& namespaceNode)
352 return eval(contextNode, expr);
361 const OUString& aName)
363 std::scoped_lock
const g(
m_Mutex);
366 Reference< XXPathExtension >
const xExtension(
376 Reference< XXPathExtension>
const& xExtension)
378 if (!xExtension.is()) {
381 std::scoped_lock
const g(
m_Mutex);
386extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
388 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any>
const&)
Reference< XComponentContext > m_xContext
virtual void SAL_CALL registerNS(const OUString &aPrefix, const OUString &aURI) override
CXPathAPI(const css::uno::Reference< css::uno::XComponentContext > &)
virtual css::uno::Reference< css::xml::xpath::XXPathObject > SAL_CALL evalNS(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str, const css::uno::Reference< css::xml::dom::XNode > &namespaceNode) override
same as eval but registers all namespace declarations found on namespaceNode
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL selectSingleNode(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str) override
Use an XPath string to select a single node.
virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL selectSingleNodeNS(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str, const css::uno::Reference< css::xml::dom::XNode > &namespaceNode) override
Use an XPath string to select a single node.
virtual css::uno::Reference< css::xml::dom::XNodeList > SAL_CALL selectNodeList(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str) override
Use an XPath string to select a nodelist.
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL unregisterNS(const OUString &aPrefix, const OUString &aURI) override
const css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual void SAL_CALL registerExtension(const OUString &aName) override
uses the service manager to create an instance of the service denoted by aName.
virtual css::uno::Reference< css::xml::dom::XNodeList > SAL_CALL selectNodeListNS(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str, const css::uno::Reference< css::xml::dom::XNode > &namespaceNode) override
Use an XPath string to select a nodelist.
extensions_t m_extensions
virtual css::uno::Reference< css::xml::xpath::XXPathObject > SAL_CALL eval(const css::uno::Reference< css::xml::dom::XNode > &contextNode, const OUString &str) override
evaluates an XPath string.
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL registerExtensionInstance(const css::uno::Reference< css::xml::xpath::XXPathExtension > &aExtension) override
registers the given extension instance to be used by XPath evaluations performed through this XPathAP...
#define SAL_WARN(area, stream)
static void structured_error_func(void *, xmlErrorPtr error)
static void lcl_collectNamespaces(nsmap_t &rNamespaces, Reference< XNode > const &xNamespaceNode)
std::map< OUString, OUString > nsmap_t
static void lcl_registerExtensions(xmlXPathContextPtr ctx, const extensions_t &extensions)
std::vector< css::uno::Reference< css::xml::xpath::XXPathExtension > > extensions_t
static void generic_error_func(void *, const char *format,...)
static void lcl_collectRegisterNamespaces(CXPathAPI &rAPI, Reference< XNode > const &xNamespaceNode)
static void lcl_registerNamespaces(xmlXPathContextPtr ctx, const nsmap_t &nsmap)
static OUString make_error_message(xmlErrorPtr pError)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
unsigned _Unwind_Word __attribute__((__mode__(__word__)))
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * unoxml_CXPathAPI_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)