浏览代码

HPCC-18504 Make WsEcl libxslt max complexity parameters configurable

The WsEcl result stylesheet is recursive and can fail for large complex
datasets.  Raise libxslt maxTeplateVars and maxTemplateDepth
default values and allow the service to configure them.

Also add a generic mechanism for adding xslt configuration values to
the ws_ecl config.  Any ws_ecl configuration element starting with
"xslt" will be passed as configuration to the xslt processor.

Signed-off-by: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Anthony Fishbeck 7 年之前
父节点
当前提交
b8d8e07505

+ 14 - 13
common/wuwebview/wuwebview.cpp

@@ -291,15 +291,15 @@ class WuWebView : public CInterface,
 public:
     IMPLEMENT_IINTERFACE
 
-    WuWebView(IConstWorkUnit &wu, const char *_target, const char *queryname, const char *wdir, bool mapEspDir, bool delay=true) :
-        manifestIncludePathsSet(false), dir(wdir), mapEspDirectories(mapEspDir), delayedDll(delay), target(_target)
+    WuWebView(IConstWorkUnit &wu, const char *_target, const char *queryname, const char *wdir, bool mapEspDir, bool delay, IPropertyTree *xsltcfg) :
+        manifestIncludePathsSet(false), dir(wdir), mapEspDirectories(mapEspDir), delayedDll(delay), target(_target), xsltConfig(xsltcfg)
     {
         name.set(queryname);
         setWorkunit(wu);
     }
 
-    WuWebView(const char *wuid, const char *_target, const char *queryname, const char *wdir, bool mapEspDir, bool delay=true) :
-        manifestIncludePathsSet(false), dir(wdir), mapEspDirectories(mapEspDir), delayedDll(delay), target(_target)
+    WuWebView(const char *wuid, const char *_target, const char *queryname, const char *wdir, bool mapEspDir, bool delay, IPropertyTree *xsltcfg) :
+        manifestIncludePathsSet(false), dir(wdir), mapEspDirectories(mapEspDir), delayedDll(delay), target(_target), xsltConfig(xsltcfg)
     {
         name.set(queryname);
         setWorkunit(wuid);
@@ -356,6 +356,7 @@ protected:
     Owned<IConstWorkUnit> cw;
     Owned<ILoadedDllEntry> dll;
     Owned<IPropertyTree> manifest;
+    Linked<IPropertyTree> xsltConfig;
     StringAttr target;
     StringAttr dir;
     StringAttr username;
@@ -662,7 +663,7 @@ void WuWebView::renderExpandedResults(const char *viewName, WuExpandedResultBuff
     if (strieq(type, "xml"))
         return out.swapWith(expanded.buffer);
 
-    Owned<IXslTransform> t = getXslProcessor()->createXslTransform();
+    Owned<IXslTransform> t = getXslProcessor()->createXslTransform(xsltConfig);
     StringBuffer cacheId(viewName);
     cacheId.append('@').append(dllname.str()); //using dllname, cloned workunits can share cache entry
     t->setIncludeHandler(this);
@@ -759,7 +760,7 @@ void WuWebView::applyResultsXSLT(const char *filename, const char *xml, StringBu
     buffer.appendDatasetsFromXML(xml);
     buffer.appendManifestSchemas(*ensureManifest(), loadDll());
 
-    Owned<IXslTransform> t = getXslProcessor()->createXslTransform();
+    Owned<IXslTransform> t = getXslProcessor()->createXslTransform(xsltConfig);
     t->setIncludeHandler(this);
     //override default behavior using filename as cache identifier, there's a chance includes are
     //mapped to resources and need to be distinguished in cache
@@ -935,11 +936,11 @@ IConstWUQuery* WuWebView::getEmbeddedQuery()
     return embeddedWU->getQuery();
 }
 
-extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char *target, const char *queryname, const char *dir, bool mapEspDirectories)
+extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char *target, const char *queryname, const char *dir, bool mapEspDirectories, IPropertyTree *xsltcfg)
 {
     try
     {
-        return new WuWebView(wu, target, queryname, dir, mapEspDirectories);
+        return new WuWebView(wu, target, queryname, dir, mapEspDirectories, true, xsltcfg);
     }
     catch (IException *e)
     {
@@ -954,11 +955,11 @@ extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char
     return NULL;
 }
 
-extern WUWEBVIEW_API IWuWebView *createWuWebView(const char *wuid, const char *target, const char *queryname, const char *dir, bool mapEspDirectories)
+extern WUWEBVIEW_API IWuWebView *createWuWebView(const char *wuid, const char *target, const char *queryname, const char *dir, bool mapEspDirectories, IPropertyTree *xsltcfg)
 {
     try
     {
-        return new WuWebView(wuid, target, queryname, dir, mapEspDirectories);
+        return new WuWebView(wuid, target, queryname, dir, mapEspDirectories, true, xsltcfg);
     }
     catch (IException *e)
     {
@@ -1033,7 +1034,7 @@ extern WUWEBVIEW_API void getWuResourceByPath(const char *path, MemoryBuffer &mb
     StringBuffer wuid, target, queryname;
     getQueryInfoFromPath(path, "res", target, queryname, wuid);
 
-    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true);
+    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true, nullptr);
     if (!web)
         throw MakeStringException(WUWEBERR_WorkUnitNotFound, "Cannot open workunit");
     mimetype.append(mimeTypeFromFileExt(strrchr(path, '.')));
@@ -1046,7 +1047,7 @@ extern WUWEBVIEW_API void getWuManifestByPath(const char *path, StringBuffer &mf
     StringBuffer wuid, target, queryname;
     getQueryInfoFromPath(path, "manifest", target, queryname, wuid);
 
-    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true);
+    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true, nullptr);
     if (!web)
         throw MakeStringException(WUWEBERR_WorkUnitNotFound, "Cannot open workunit");
     if (!web->getManifest(mf).length())
@@ -1061,7 +1062,7 @@ extern WUWEBVIEW_API void getWuResourceUrlListByPath(const char *path, StringBuf
     if (!fmt.length())
         fmt.set("xml");
 
-    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true);
+    Owned<IWuWebView> web = createWuWebView(wuid, target, queryname, NULL, true, nullptr);
     if (!web)
         throw MakeStringException(WUWEBERR_WorkUnitNotFound, "Cannot open workunit");
     StringArray urls;

+ 2 - 2
common/wuwebview/wuwebview.hpp

@@ -58,8 +58,8 @@ interface IWuWebView : extends IInterface
 
 };
 
-extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char *target, const char *queryname, const char*dir, bool mapEspDir);
-extern WUWEBVIEW_API IWuWebView *createWuWebView(const char *wuid, const char *target, const char *queryname, const char*dir, bool mapEspDir);
+extern WUWEBVIEW_API IWuWebView *createWuWebView(IConstWorkUnit &wu, const char *target, const char *queryname, const char*dir, bool mapEspDir, IPropertyTree *xsltcfg);
+extern WUWEBVIEW_API IWuWebView *createWuWebView(const char *wuid, const char *target, const char *queryname, const char*dir, bool mapEspDir, IPropertyTree *xsltcfg);
 
 extern WUWEBVIEW_API void getWuResourceUrlListByPath(const char *path, StringBuffer &fmt, StringBuffer &content, const char *prefix);
 extern WUWEBVIEW_API void getWuManifestByPath(const char *path, StringBuffer &mf);

+ 1 - 1
esp/services/ecldirect/EclDirectService.cpp

@@ -314,7 +314,7 @@ bool CEclDirectEx::onRunEclEx(IEspContext &context, IEspRunEclExRequest & req, I
     {
         StringBuffer results;
         CRunEclExFormat outputFormat = req.getFormat();
-        Owned<IWuWebView> web = createWuWebView(wuid.str(), NULL, NULL, getCFD(), true);
+        Owned<IWuWebView> web = createWuWebView(wuid.str(), NULL, NULL, getCFD(), true, nullptr);
         if (!web)
             results.appendf("<Exception><Source>ESP</Source><Message>Failed loading result workunit %s</Message></Exception>", wuid.str());
         else if (outputFormat == CRunEclExFormat_Table)

+ 17 - 12
esp/services/ws_ecl/ws_ecl_service.cpp

@@ -295,6 +295,11 @@ bool CWsEclService::init(const char * name, const char * type, IPropertyTree * c
     }
 
     translator = new wsEclTypeTranslator();
+
+    Owned<IPropertyTreeIterator> xsltProps = serviceTree->getElements("xslt*");
+    ForEach(*xsltProps)
+        xsltConfig->addPropTree(xsltProps->query().queryName(), LINK(&xsltProps->query()));
+
     return true;
 }
 
@@ -491,7 +496,7 @@ static void splitLookupInfo(IProperties *parms, const char *&s, StringBuffer &wu
 void CWsEclBinding::xsltTransform(const char* xml, unsigned int len, const char* xslFileName, IProperties *params, StringBuffer& ret)
 {
     Owned<IXslProcessor> proc  = getXslProcessor();
-    Owned<IXslTransform> trans = proc->createXslTransform();
+    Owned<IXslTransform> trans = proc->createXslTransform(queryXsltConfig());
 
     trans->setXmlSource(xml, len);
 
@@ -880,7 +885,7 @@ int CWsEclBinding::getWsEclLinks(IEspContext &context, CHttpRequest* request, CH
     xml.append("</links>");
 
     Owned<IXslProcessor> xslp = getXslProcessor();
-    Owned<IXslTransform> xform = xslp->createXslTransform();
+    Owned<IXslTransform> xform = xslp->createXslTransform(queryXsltConfig());
     xform->loadXslFromFile(StringBuffer(getCFD()).append("./xslt/wsecl3_links.xslt").str());
     xform->setXmlSource(xml.str(), xml.length());
 
@@ -1400,7 +1405,7 @@ int CWsEclBinding::getGenForm(IEspContext &context, CHttpRequest* request, CHttp
         ws->getText("description", infoSv);
     }
 
-    Owned<IWuWebView> web = createWuWebView(*wu, wuinfo.qsetname.get(), wuinfo.queryname.get(), getCFD(), true);
+    Owned<IWuWebView> web = createWuWebView(*wu, wuinfo.qsetname.get(), wuinfo.queryname.get(), getCFD(), true, queryXsltConfig());
     if (web)
     {
         if (!help.length())
@@ -1444,7 +1449,7 @@ int CWsEclBinding::getGenForm(IEspContext &context, CHttpRequest* request, CHttp
     formxml.append("</CustomViews>");
     formxml.append("</FormInfo>");
 
-    Owned<IXslTransform> xform = xslp->createXslTransform();
+    Owned<IXslTransform> xform = xslp->createXslTransform(queryXsltConfig());
 
     StringBuffer xslfile(getCFD());
     if (box)
@@ -1664,7 +1669,7 @@ int CWsEclBinding::getXmlTestForm(IEspContext &context, CHttpRequest* request, C
     getEspUrlParams(context,params,excludes);
 
     Owned<IXslProcessor> xslp = getXslProcessor();
-    Owned<IXslTransform> xform = xslp->createXslTransform();
+    Owned<IXslTransform> xform = xslp->createXslTransform(queryXsltConfig());
     xform->loadXslFromFile(StringBuffer(getCFD()).append("./xslt/wsecl3_xmltest.xsl").str());
 
     StringBuffer srcxml;
@@ -1732,7 +1737,7 @@ int CWsEclBinding::getJsonTestForm(IEspContext &context, CHttpRequest* request,
     StringBuffer header("Content-Type: application/json; charset=UTF-8");
 
     Owned<IXslProcessor> xslp = getXslProcessor();
-    Owned<IXslTransform> xform = xslp->createXslTransform();
+    Owned<IXslTransform> xform = xslp->createXslTransform(queryXsltConfig());
     xform->loadXslFromFile(StringBuffer(getCFD()).append("./xslt/wsecl3_jsontest.xsl").str());
 
     StringBuffer encodedMsg;
@@ -1878,7 +1883,7 @@ int CWsEclBinding::submitWsEclWorkunit(IEspContext & context, WsEclWuInfo &wsinf
     //don't wait indefinitely, in case submitted to an inactive queue wait max + 5 mins
     if (!async && waitForWorkUnitToComplete(wuid.str(), wsecl->workunitTimeout))
     {
-        Owned<IWuWebView> web = createWuWebView(wuid.str(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true);
+        Owned<IWuWebView> web = createWuWebView(wuid.str(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());
         if (!web)
         {
             DBGLOG("WS-ECL failed to create WuWebView for workunit %s", wuid.str());
@@ -1897,7 +1902,7 @@ int CWsEclBinding::submitWsEclWorkunit(IEspContext & context, WsEclWuInfo &wsinf
     {
         if (!async)
             DBGLOG("WS-ECL request timed out, WorkUnit %s", wuid.str());
-        Owned<IWuWebView> web = createWuWebView(wuid.str(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true);
+        Owned<IWuWebView> web = createWuWebView(wuid.str(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());
         web->createWuidResponse(out, flags);
     }
 
@@ -2009,7 +2014,7 @@ int CWsEclBinding::onSubmitQueryOutput(IEspContext &context, CHttpRequest* reque
             else
             {
                 IConstWorkUnit *wu = wsinfo.ensureWorkUnit();
-                Owned<IWuWebView> web = createWuWebView(*wu, wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true);
+                Owned<IWuWebView> web = createWuWebView(*wu, wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());
                 if (web.get())
                     web->expandResults(roxieresp.str(), output, xmlflags);
             }
@@ -2052,7 +2057,7 @@ int CWsEclBinding::onSubmitQueryOutputView(IEspContext &context, CHttpRequest* r
     if (strieq(clustertype.str(), "roxie"))
     {
         sendRoxieRequest(wsinfo.qsetname.get(), soapmsg, output, status, wsinfo.queryname, false, "text/xml");
-        Owned<IWuWebView> web = createWuWebView(*wu, wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true);
+        Owned<IWuWebView> web = createWuWebView(*wu, wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());
         if (!view)
             web->applyResultsXSLT(xsltfile.str(), output.str(), html);
         else
@@ -2284,7 +2289,7 @@ int CWsEclBinding::getRestURL(IEspContext *ctx, CHttpRequest *request, CHttpResp
             appendXMLCloseTag(xml, "resturl");
 
             Owned<IXslProcessor> xslp = getXslProcessor();
-            Owned<IXslTransform> xform = xslp->createXslTransform();
+            Owned<IXslTransform> xform = xslp->createXslTransform(queryXsltConfig());
             xform->loadXslFromFile(StringBuffer(getCFD()).append("./xslt/wsecl3_url.xslt").str());
             xform->setXmlSource(xml.str(), xml.length());
 
@@ -2781,7 +2786,7 @@ int CWsEclBinding::HandleSoapRequest(CHttpRequest* request, CHttpResponse* respo
             else
             {
                 WsEclWuInfo wsinfo(wuid.str(), target.str(), queryname.str(), ctx->queryUserId(), ctx->queryPassword());
-                Owned<IWuWebView> web = createWuWebView(*wsinfo.ensureWorkUnit(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true);
+                Owned<IWuWebView> web = createWuWebView(*wsinfo.ensureWorkUnit(), wsinfo.qsetname.get(), wsinfo.queryname.get(), getCFD(), true, queryXsltConfig());
                 if (web.get())
                     web->expandResults(output.str(), soapresp, xmlflags);
             }

+ 3 - 1
esp/services/ws_ecl/ws_ecl_service.hpp

@@ -103,6 +103,7 @@ class CWsEclService : public CInterface,
 {
 public:
     MapStringToMyClass<ISmartSocketFactory> connMap;
+    Owned<IPropertyTree> xsltConfig = createPTree("XsltConfig");
     StringArray targets;
     StringAttr auth_method;
     StringAttr portal_URL;
@@ -145,7 +146,8 @@ public:
     }
     
     virtual void setXslProcessor(IInterface * xslp){}
-    
+    inline IPropertyTree *queryXsltConfig(){return wsecl ? wsecl->xsltConfig : nullptr;}
+
     StringBuffer &generateNamespace(IEspContext &context, CHttpRequest* request, const char *serv, const char *method, StringBuffer &ns);
 
     virtual int getQualifiedNames(IEspContext& ctx, MethodInfoArray & methods){return 0;}

+ 3 - 3
esp/services/ws_workunits/ws_workunitsHelpers.cpp

@@ -1812,7 +1812,7 @@ bool WsWuInfo::getResourceInfo(StringArray &viewnames, StringArray &urls, unsign
         return true;
     try
     {
-        Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
+        Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false, nullptr);
         if (wv)
         {
             if (flags & WUINFO_IncludeResultsViewNames)
@@ -1836,7 +1836,7 @@ unsigned WsWuInfo::getResourceURLCount()
 {
     try
     {
-        Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
+        Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false, nullptr);
         if (wv)
             return wv->getResourceURLCount();
     }
@@ -2125,7 +2125,7 @@ void WsWuInfo::getWorkunitResTxt(MemoryBuffer& buf)
 
 IConstWUQuery* WsWuInfo::getEmbeddedQuery()
 {
-    Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
+    Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false, nullptr);
     if (wv)
         return wv->getEmbeddedQuery();
 

+ 1 - 1
esp/services/ws_workunits/ws_workunitsService.cpp

@@ -1617,7 +1617,7 @@ bool CWsWorkunitsEx::onWUResultView(IEspContext &context, IEspWUResultViewReques
     ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
     PROGLOG("WUResultView: %s", wuid.str());
 
-    Owned<IWuWebView> wv = createWuWebView(wuid.str(), NULL, NULL, getCFD(), true);
+    Owned<IWuWebView> wv = createWuWebView(wuid.str(), NULL, NULL, getCFD(), true, nullptr);
     StringBuffer html;
     wv->renderSingleResult(req.getViewName(), req.getResultName(), html);
     resp.setResult(html.str());

+ 6 - 0
initfiles/componentfiles/configxml/@temp/esp_service.xsl

@@ -907,6 +907,12 @@ xmlns:seisint="http://seisint.com"  xmlns:set="http://exslt.org/sets" exclude-re
                     <WorkunitTimeout><xsl:value-of select="@workunitTimeout"/></WorkunitTimeout>
                 </xsl:if>
                 <WorkunitTimeout><xsl:value-of select="@workunitTimeout"/></WorkunitTimeout>
+                <xsl:if test="string(@xsltMaxDepth)!=''">
+                    <xsltMaxDepth><xsl:value-of select="@xsltMaxDepth"/></xsltMaxDepth>
+                </xsl:if>
+                <xsl:if test="string(@xsltMaxVars)!=''">
+                    <xsltMaxVars><xsl:value-of select="@xsltMaxVars"/></xsltMaxVars>
+                </xsl:if>
                 <VIPS>
                     <xsl:for-each select="ProcessCluster">
                         <xsl:if test="string(@roxie) != '' and string(@vip) != ''">

+ 14 - 0
initfiles/componentfiles/configxml/esp_service_wsecl2.xsd

@@ -157,6 +157,20 @@
                     </xs:appinfo>
                 </xs:annotation>
             </xs:attribute>
+            <xs:attribute name="xsltMaxDepth" type="xs:unsignedInt" use="optional" default="100000">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <tooltip>Maximum libxslt stylesheet template depth (affects size and complexity of dataset that can be rendered)</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="xsltMaxVars" type="xs:unsignedInt" use="optional" default="1000000">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <tooltip>Maximum libxslt stylesheet template variables (affects size and complexity of dataset that can be rendered)</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
         </xs:complexType>
     </xs:element>
 </xs:schema>

+ 18 - 5
system/xmllib/libxslt_processor.cpp

@@ -330,7 +330,7 @@ class CLibXslTransform : public CInterface, implements IXslTransform
 public:
     IMPLEMENT_IINTERFACE;
 
-    CLibXslTransform();
+    CLibXslTransform(IPropertyTree *cfg);
     ~CLibXslTransform();
     virtual int transform();
     virtual int transform(StringBuffer &s);
@@ -406,6 +406,7 @@ public:
     void clearMessages(){messages.clear();}
 
 public:
+    Owned<IPropertyTree> xslConfig;
     Owned<IProperties> xslParameters;
     Owned<CLibXsltSource> xslSrc;
     Owned<CLibXmlSource> xmlSrc;
@@ -418,11 +419,13 @@ public:
     void *userData;
 };
 
-CLibXslTransform::CLibXslTransform()
+CLibXslTransform::CLibXslTransform(IPropertyTree *cfg)
 {
     userData = NULL;
     msgfn.setown(createExternalFunction("message", libxsltCustomMessageHandler));
     setExternalFunction(SEISINT_XSLTEXT_NAMESPACE, msgfn, true);
+    if (cfg)
+        xslConfig.set(cfg);
 }
 
 CLibXslTransform::~CLibXslTransform()
@@ -529,6 +532,16 @@ int CLibXslTransform::transform(xmlChar **xmlbuff, int &len)
     if (!ctxt)
         throw MakeStringException(XSLERR_CouldNotCreateTransform, "Failed creating libxslt Transform Context");
     ctxt->_private = this;
+    if (xslConfig)
+    {
+        ctxt->maxTemplateDepth = xslConfig->getPropInt("xsltMaxDepth", 100000);
+        ctxt->maxTemplateVars = xslConfig->getPropInt("xsltMaxVars", 1000000);
+    }
+    else
+    {
+        ctxt->maxTemplateDepth = 100000; //we use some very highly nested stylesheets
+        ctxt->maxTemplateVars = 1000000;
+    }
 
     HashIterator h(functions);
     ForEach (h)
@@ -696,7 +709,7 @@ public:
 
     CLibXslProcessor();
     ~CLibXslProcessor();
-    virtual IXslTransform *createXslTransform();
+    virtual IXslTransform *createXslTransform(IPropertyTree *cfg);
     virtual int execute(IXslTransform *pITransform);
 
     virtual int setDefIncludeHandler(IIncludeHandler* handler){includeHandler.set(handler); return 0;}
@@ -741,9 +754,9 @@ extern IXslProcessor* getXslProcessor()
     return LINK(&xslProcessor);
 }
 
-IXslTransform *CLibXslProcessor::createXslTransform()
+IXslTransform *CLibXslProcessor::createXslTransform(IPropertyTree *cfg)
 {
-    return new CLibXslTransform();
+    return new CLibXslTransform(cfg);
 }
 
 int CLibXslProcessor::execute(IXslTransform *pITransform)

+ 1 - 1
system/xmllib/xalan_processor.cpp

@@ -269,7 +269,7 @@ CXslProcessor::~CXslProcessor()
 {
 }
 
-IXslTransform *CXslProcessor::createXslTransform()
+IXslTransform *CXslProcessor::createXslTransform(IPropertyTree *cfg)
 {
     return new CXslTransform(inch.get());
 }

+ 1 - 1
system/xmllib/xalan_processor.ipp

@@ -590,7 +590,7 @@ public:
 
     CXslProcessor();
     ~CXslProcessor();
-    virtual IXslTransform *createXslTransform();
+    virtual IXslTransform *createXslTransform(IPropertyTree *cfg = nullptr);
     virtual int execute(IXslTransform *pITransform);
 
     virtual int setDefIncludeHandler(IIncludeHandler* handler){inch.set(handler); return 0;}

+ 1 - 1
system/xmllib/xslprocessor.hpp

@@ -112,7 +112,7 @@ public:
 
 interface XMLLIB_API IXslProcessor : public IInterface
 {
-    virtual IXslTransform *createXslTransform() = 0;
+    virtual IXslTransform *createXslTransform(IPropertyTree *cfg = nullptr) = 0;
  
     // execute - runs the transformation placing the results in the specified output location
     //