void TXFMXPath::evaluateExpr(DOMNode *h, safeBuffer inexpr) { // Temporarily add any necessary name spaces into the document XSECXPathNodeList addedNodes; setXPathNS(document, XPathAtts, addedNodes, formatter, mp_nse); XPathProcessorImpl xppi; // The processor XercesParserLiaison xpl; #if XALAN_VERSION_MAJOR == 1 && XALAN_VERSION_MINOR > 10 XercesDOMSupport xds(xpl); #else XercesDOMSupport xds; #endif XPathEvaluator xpe; XPathFactoryDefault xpf; XPathConstructionContextDefault xpcc; XalanDocument * xd; XalanNode * contextNode; // Xalan can throw exceptions in all functions, so do one broad catch point. try { // Map to Xalan xd = xpl.createDocument(document); // For performing mapping XercesDocumentWrapper *xdw = xpl.mapDocumentToWrapper(xd); XercesWrapperNavigator xwn(xdw); // Map the "here" node - but only if part of current document XalanNode * hereNode = NULL; if (h->getOwnerDocument() == document) { hereNode = xwn.mapNode(h); if (hereNode == NULL) { hereNode = findHereNodeFromXalan(&xwn, xd, h); if (hereNode == NULL) { throw XSECException(XSECException::XPathError, "Unable to find here node in Xalan Wrapper map"); } } } // Now work out what we have to set up in the new processing TXFMBase::nodeType inputType = input->getNodeType(); XalanDOMString cd; // For the moment assume the root is the context const XalanDOMChar * cexpr; safeBuffer contextExpr; switch (inputType) { case DOM_NODE_DOCUMENT : case DOM_NODE_XPATH_NODESET : // do XPath over the whole document and, if the input was an // XPath Nodeset, then later intersect the result with the input nodelist cd = XalanDOMString("/"); // Root node cexpr = cd.c_str(); // The context node is the "root" node contextNode = xpe.selectSingleNode( xds, xd, cexpr, xd->getDocumentElement()); break; case DOM_NODE_DOCUMENT_FRAGMENT : { // Need to map the DOM_Node that we are given from the input to the appropriate XalanNode // Create the XPath expression to find the node if (input->getFragmentId() != NULL) { contextExpr.sbTranscodeIn("//descendant-or-self::node()[attribute::Id='"); contextExpr.sbXMLChCat(input->getFragmentId()); contextExpr.sbXMLChCat("']"); // Map the node contextNode = xpe.selectSingleNode( xds, xd, contextExpr.rawXMLChBuffer(), //XalanDOMString((char *) contextExpr.rawBuffer()).c_str(), xd->getDocumentElement()); if (contextNode == NULL) { // Last Ditch contextNode = xwn.mapNode(input->getFragmentNode()); } } else contextNode = xwn.mapNode(input->getFragmentNode()); if (contextNode == NULL) { // Something wrong throw XSECException(XSECException::XPathError, "Error mapping context node"); } break; } default : throw XSECException(XSECException::XPathError); // Should never get here } safeBuffer str; XPathEnvSupportDefault xpesd; XObjectFactoryDefault xof; XPathExecutionContextDefault xpec(xpesd, xds, xof); ElementPrefixResolverProxy pr(xd->getDocumentElement(), xpesd, xds); // Work around the fact that the XPath implementation is designed for XSLT, so does // not allow here() as a NCName. // THIS IS A KLUDGE AND SHOULD BE DONE BETTER int offset = 0; safeBuffer k(KLUDGE_PREFIX); k.sbStrcatIn(":"); offset = inexpr.sbStrstr("here()"); while (offset >= 0) { if (offset == 0 || offset == 1 || (!(inexpr[offset - 1] == ':' && inexpr[offset - 2] != ':') && separator(inexpr[offset - 1]))) { inexpr.sbStrinsIn(k.rawCharBuffer(), offset); } offset = inexpr.sbOffsetStrstr("here()", offset + 11); } // Install the External function in the Environment handler if (hereNode != NULL) { xpesd.installExternalFunctionLocal(XalanDOMString(URI_ID_DSIG), XalanDOMString("here"), DSIGXPathHere(hereNode)); } str.sbStrcpyIn("(descendant-or-self::node() | descendant-or-self::node()/attribute::* | descendant-or-self::node()/namespace::*)["); str.sbStrcatIn(inexpr); str.sbStrcatIn("]"); XPath * xp = xpf.create(); XalanDOMString Xexpr((char *) str.rawBuffer()); xppi.initXPath(*xp, xpcc, Xexpr, pr); // Now resolve XObjectPtr xObj = xp->execute(contextNode, pr, xpec); // Now map to a list that others can use (naieve list at this time) const NodeRefListBase& lst = xObj->nodeset(); int size = (int) lst.getLength(); const DOMNode *item; for (int i = 0; i < size; ++ i) { if (lst.item(i) == xd) m_XPathMap.addNode(document); else { item = xwn.mapNode(lst.item(i)); m_XPathMap.addNode(item); } } if (inputType == DOM_NODE_XPATH_NODESET) { //the input list was a XPATH nodeset, so we must intersect the // results of the XPath processing done above with the input nodeset m_XPathMap.intersect(input->getXPathNodeList()); } } catch (XSLException &e) { safeBuffer msg; // Whatever happens - fix any changes to the original document clearXPathNS(document, addedNodes, formatter, mp_nse); // Collate the exception message into an XSEC message. msg.sbTranscodeIn("Xalan Exception : "); #if defined (XSEC_XSLEXCEPTION_RETURNS_DOMSTRING) msg.sbXMLChCat(e.getType().c_str()); #else msg.sbXMLChCat(e.getType()); #endif msg.sbXMLChCat(" caught. Message : "); msg.sbXMLChCat(e.getMessage().c_str()); throw XSECException(XSECException::XPathError, msg.rawXMLChBuffer()); } clearXPathNS(document, addedNodes, formatter, mp_nse); }
XSECXPathNodeList * TXFMXPathFilter::evaluateSingleExpr(DSIGXPathFilterExpr *expr) { // Have a single expression that we wish to find the resultant nodeset // for XSECXPathNodeList addedNodes; setXPathNS(document, expr->mp_NSMap, addedNodes, mp_formatter, mp_nse); XPathProcessorImpl xppi; // The processor XercesParserLiaison xpl; #if XALAN_VERSION_MAJOR == 1 && XALAN_VERSION_MINOR > 10 XercesDOMSupport xds(xpl); #else XercesDOMSupport xds; #endif XPathEvaluator xpe; XPathFactoryDefault xpf; XPathConstructionContextDefault xpcc; XalanDocument * xd; XalanNode * contextNode; // Xalan can throw exceptions in all functions, so do one broad catch point. try { // Map to Xalan xd = xpl.createDocument(document); // For performing mapping XercesDocumentWrapper *xdw = xpl.mapDocumentToWrapper(xd); XercesWrapperNavigator xwn(xdw); // Map the "here" node XalanNode * hereNode = NULL; hereNode = xwn.mapNode(expr->mp_xpathFilterNode); if (hereNode == NULL) { hereNode = findHereNodeFromXalan(&xwn, xd, expr->mp_exprTextNode); if (hereNode == NULL) { throw XSECException(XSECException::XPathFilterError, "Unable to find here node in Xalan Wrapper map"); } } // Now work out what we have to set up in the new processing XalanDOMString cd; // For XPath Filter, the root is always the context node cd = XalanDOMString("/"); // Root node // The context node is the "root" node contextNode = xpe.selectSingleNode( xds, xd, cd.c_str(), xd->getDocumentElement()); XPathEnvSupportDefault xpesd; XObjectFactoryDefault xof; XPathExecutionContextDefault xpec(xpesd, xds, xof); ElementPrefixResolverProxy pr(xd->getDocumentElement(), xpesd, xds); // Work around the fact that the XPath implementation is designed for XSLT, so does // not allow here() as a NCName. // THIS IS A KLUDGE AND SHOULD BE DONE BETTER int offset = 0; safeBuffer k(KLUDGE_PREFIX); k.sbStrcatIn(":"); // Map the expression into a local code page string (silly - should be XMLCh) safeBuffer exprSB; exprSB << (*mp_formatter << expr->m_expr.rawXMLChBuffer()); offset = exprSB.sbStrstr("here()"); while (offset >= 0) { if (offset == 0 || offset == 1 || (!(exprSB[offset - 1] == ':' && exprSB[offset - 2] != ':') && separator(exprSB[offset - 1]))) { exprSB.sbStrinsIn(k.rawCharBuffer(), offset); } offset = exprSB.sbOffsetStrstr("here()", offset + 11); } // Install the External function in the Environment handler if (hereNode != NULL) { xpesd.installExternalFunctionLocal(XalanDOMString(URI_ID_DSIG), XalanDOMString("here"), DSIGXPathHere(hereNode)); } XPath * xp = xpf.create(); XalanDOMString Xexpr((char *) exprSB.rawBuffer()); xppi.initXPath(*xp, xpcc, Xexpr, pr); // Now resolve XObjectPtr xObj = xp->execute(contextNode, pr, xpec); // Now map to a list that others can use (naieve list at this time) const NodeRefListBase& lst = xObj->nodeset(); int size = (int) lst.getLength(); const DOMNode *item; XSECXPathNodeList * ret; XSECnew(ret, XSECXPathNodeList); Janitor<XSECXPathNodeList> j_ret(ret); for (int i = 0; i < size; ++ i) { if (lst.item(i) == xd) ret->addNode(document); else { item = xwn.mapNode(lst.item(i)); ret->addNode(item); } } xpesd.uninstallExternalFunctionGlobal(XalanDOMString(URI_ID_DSIG), XalanDOMString("here")); clearXPathNS(document, addedNodes, mp_formatter, mp_nse); j_ret.release(); return ret; } catch (XSLException &e) { safeBuffer msg; // Whatever happens - fix any changes to the original document clearXPathNS(document, addedNodes, mp_formatter, mp_nse); // Collate the exception message into an XSEC message. msg.sbTranscodeIn("Xalan Exception : "); #if defined (XSEC_XSLEXCEPTION_RETURNS_DOMSTRING) msg.sbXMLChCat(e.getType().c_str()); #else msg.sbXMLChCat(e.getType()); #endif msg.sbXMLChCat(" caught. Message : "); msg.sbXMLChCat(e.getMessage().c_str()); throw XSECException(XSECException::XPathFilterError, msg.rawXMLChBuffer()); } catch (...) { clearXPathNS(document, addedNodes, mp_formatter, mp_nse); throw; } return NULL; }