Sfoglia il codice sorgente

Merge pull request #10227 from afishbeck/soapcallReadInlineXml

HPCC-17974 Support xpath('<>') in soapcall response layout

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday 8 anni fa
parent
commit
10e012e9a1

+ 4 - 4
common/thorhelper/thorsoapcall.cpp

@@ -1766,7 +1766,7 @@ private:
             tail = "Dataset/Row";
 
         CMatchCB matchCB(*this, url, tail, meta);
-        Owned<IXMLParse> xmlParser = createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, false);
+        Owned<IXMLParse> xmlParser = createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, (master->flags&SOAPFusescontents)!=0);
         while (xmlParser->next());
     }
 
@@ -1776,7 +1776,7 @@ private:
         if(master->rowTransformer && master->inputpath.get())
             path.append(master->inputpath.get());
         CMatchCB matchCB(*this, url, NULL, meta);
-        Owned<IXMLParse> xmlParser = createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, false);
+        Owned<IXMLParse> xmlParser = createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, (master->flags&SOAPFusescontents)!=0);
         while (xmlParser->next());
     }
 
@@ -1788,9 +1788,9 @@ private:
         CMatchCB matchCB(*this, url, NULL, meta);
         Owned<IXMLParse> xmlParser;
         if (strieq(master->acceptType.str(), "application/json"))
-            xmlParser.setown(createJSONParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, false, true));
+            xmlParser.setown(createJSONParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, (master->flags&SOAPFusescontents)!=0, true));
         else
-            xmlParser.setown(createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, false));
+            xmlParser.setown(createXMLParse((const void *)response.str(), (unsigned)response.length(), path.str(), matchCB, options, (master->flags&SOAPFusescontents)!=0));
         while (xmlParser->next());
     }
 

+ 0 - 2
ecl/hqlcpp/hqlcerrors.hpp

@@ -99,7 +99,6 @@
 #define HQLERR_OverwriteMismatch                4075
 #define HQLERR_ExtendOverwriteMismatch          4076
 #define HQLERR_EmbeddedCppNotAllowed            4078
-#define HQLERR_ContentsInSoapCall               4079
 #define HQLERR_FullKeyedNeedsFile               4081
 #define HQLERR_ExpectedConstant                 4082
 #define HQLERR_AccessRowBlobInsideChildQuery    4083
@@ -406,7 +405,6 @@
 #define HQLERR_OverwriteMismatch_Text           "OVERWRITE is required on all outputs to NAMED(%s)"
 #define HQLERR_ExtendOverwriteMismatch_Text     "OVERWRITE/EXTEND should be consistent on all outputs to NAMED(%s)"
 #define HQLERR_EmbeddedCppNotAllowed_Text       "Insufficient access rights to use embedded code"
-#define HQLERR_ContentsInSoapCall_Text          "Tag contents syntax <> is not supported by SOAPCALL"
 #define HQLERR_FullKeyedNeedsFile_Text          "RIGHT side of a full keyed join must be a disk file"
 #define HQLERR_ExpectedConstant_Text            "Expression is not constant: %s"
 #define HQLERR_AccessRowBlobInsideChildQuery_Text "Unimplemented: Cannot access row blob inside a child query, contact tech support"

+ 60 - 62
ecl/hqlcpp/hqlhtcpp.cpp

@@ -17593,36 +17593,6 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySOAP(BuildCtx & ctx, IHqlExpre
         }
     }
 
-    //virtual unsigned getFlags()
-    {
-        StringBuffer flags;
-        if (expr->hasAttribute(groupAtom))
-            flags.append("|SOAPFgroup");
-        if (expr->hasAttribute(onFailAtom))
-            flags.append("|SOAPFonfail");
-        if (logXml)
-            flags.append("|SOAPFlog");
-        if (expr->hasAttribute(trimAtom))
-            flags.append("|SOAPFtrim");
-        if (expr->hasAttribute(literalAtom))
-            flags.append("|SOAPFliteral");
-        if (namespaceAttr)
-            flags.append("|SOAPFnamespace");
-        if (expr->hasAttribute(encodingAtom))
-            flags.append("|SOAPFencoding");
-        if (responseAttr && responseAttr->hasAttribute(noTrimAtom))
-            flags.append("|SOAPFpreserveSpace");
-        if (logMin)
-            flags.append("|SOAPFlogmin");
-        if (logText)
-            flags.append("|SOAPFlogusermsg");
-        if (expr->hasAttribute(httpHeaderAtom))
-            flags.append("|SOAPFhttpheaders");
-
-        if (flags.length())
-            doBuildUnsignedFunction(instance->classctx, "getFlags", flags.str()+1);
-    }
-
     //virtual unsigned numParallelThreads()
     doBuildUnsignedFunction(instance->startctx, "numParallelThreads", queryAttributeChild(expr, parallelAtom, 0));
 
@@ -17657,13 +17627,11 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySOAP(BuildCtx & ctx, IHqlExpre
         }
         doBuildFunctionReturn(funcctx, unknownStringType, logText);
     }
+    bool usesContents = false;
     if (!isSink)
     {
         //virtual IXmlToRowTransformer * queryTransformer()
-        bool usesContents = false;
         doBuildXmlReadMember(*instance, expr, "queryInputTransformer", usesContents);
-        if (usesContents)
-            throwError(HQLERR_ContentsInSoapCall);
 
         //virtual const char * getInputIteratorPath()
         IHqlExpression * xpath = expr->queryAttribute(xpathAtom);
@@ -17684,6 +17652,37 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySOAP(BuildCtx & ctx, IHqlExpre
             buildTransformBody(onFailCtx, onFailTransform, dataset, NULL, expr, selSeq);
         }
     }
+    //virtual unsigned getFlags()
+    {
+        StringBuffer flags;
+        if (expr->hasAttribute(groupAtom))
+            flags.append("|SOAPFgroup");
+        if (expr->hasAttribute(onFailAtom))
+            flags.append("|SOAPFonfail");
+        if (logXml)
+            flags.append("|SOAPFlog");
+        if (expr->hasAttribute(trimAtom))
+            flags.append("|SOAPFtrim");
+        if (expr->hasAttribute(literalAtom))
+            flags.append("|SOAPFliteral");
+        if (namespaceAttr)
+            flags.append("|SOAPFnamespace");
+        if (expr->hasAttribute(encodingAtom))
+            flags.append("|SOAPFencoding");
+        if (responseAttr && responseAttr->hasAttribute(noTrimAtom))
+            flags.append("|SOAPFpreserveSpace");
+        if (logMin)
+            flags.append("|SOAPFlogmin");
+        if (logText)
+            flags.append("|SOAPFlogusermsg");
+        if (expr->hasAttribute(httpHeaderAtom))
+            flags.append("|SOAPFhttpheaders");
+        if (usesContents)
+            flags.append("|SOAPFusescontents");
+
+        if (flags.length())
+            doBuildUnsignedFunction(instance->classctx, "getFlags", flags.str()+1);
+    }
     buildInstanceSuffix(instance);
     if (boundDataset)
         buildConnectInputOutput(ctx, instance, boundDataset, 0, 0);
@@ -17756,32 +17755,6 @@ ABoundActivity * HqlCppTranslator::doBuildActivityHTTP(BuildCtx & ctx, IHqlExpre
         }
     }
 
-    //virtual unsigned getFlags()
-    {
-        StringBuffer flags;
-        if (expr->hasAttribute(groupAtom))
-            flags.append("|SOAPFgroup");
-        if (expr->hasAttribute(onFailAtom))
-            flags.append("|SOAPFonfail");
-        if (logXml)
-            flags.append("|SOAPFlog");
-        if (expr->hasAttribute(trimAtom))
-            flags.append("|SOAPFtrim");
-        if (expr->hasAttribute(literalAtom))
-            flags.append("|SOAPFliteral");
-        if (namespaceAttr)
-            flags.append("|SOAPFnamespace");
-        if (logMin)
-            flags.append("|SOAPFlogmin");
-        if (logText)
-            flags.append("|SOAPFlogusermsg");
-        if (expr->hasAttribute(httpHeaderAtom))
-            flags.append("|SOAPFhttpheaders");
-
-        if (flags.length())
-            doBuildUnsignedFunction(instance->classctx, "getFlags", flags.str()+1);
-    }
-
     //virtual unsigned numParallelThreads()
     doBuildUnsignedFunction(instance->classctx, "numParallelThreads", queryAttributeChild(expr, parallelAtom, 0));
 
@@ -17811,13 +17784,11 @@ ABoundActivity * HqlCppTranslator::doBuildActivityHTTP(BuildCtx & ctx, IHqlExpre
         doBuildFunctionReturn(funcctx, unknownStringType, logText);
     }
 
+    bool usesContents = false;
     if (!isSink)
     {
         //virtual IXmlToRowTransformer * queryTransformer()
-        bool usesContents = false;
         doBuildXmlReadMember(*instance, expr, "queryInputTransformer", usesContents);
-        if (usesContents)
-            throwError(HQLERR_ContentsInSoapCall);
 
         //virtual const char * getInputIteratorPath()
         IHqlExpression * xpath = expr->queryAttribute(xpathAtom);
@@ -17835,6 +17806,33 @@ ABoundActivity * HqlCppTranslator::doBuildActivityHTTP(BuildCtx & ctx, IHqlExpre
             buildTransformBody(onFailCtx, onFail->queryChild(0), dataset, NULL, expr, selSeq);
         }
     }
+    //virtual unsigned getFlags()
+    {
+        StringBuffer flags;
+        if (expr->hasAttribute(groupAtom))
+            flags.append("|SOAPFgroup");
+        if (expr->hasAttribute(onFailAtom))
+            flags.append("|SOAPFonfail");
+        if (logXml)
+            flags.append("|SOAPFlog");
+        if (expr->hasAttribute(trimAtom))
+            flags.append("|SOAPFtrim");
+        if (expr->hasAttribute(literalAtom))
+            flags.append("|SOAPFliteral");
+        if (namespaceAttr)
+            flags.append("|SOAPFnamespace");
+        if (logMin)
+            flags.append("|SOAPFlogmin");
+        if (logText)
+            flags.append("|SOAPFlogusermsg");
+        if (expr->hasAttribute(httpHeaderAtom))
+            flags.append("|SOAPFhttpheaders");
+        if (usesContents)
+            flags.append("|SOAPFusescontents");
+
+        if (flags.length())
+            doBuildUnsignedFunction(instance->classctx, "getFlags", flags.str()+1);
+    }
     buildInstanceSuffix(instance);
     if (boundDataset)
         buildConnectInputOutput(ctx, instance, boundDataset, 0, 0);

+ 2 - 1
rtl/include/eclhelper.hpp

@@ -2190,7 +2190,8 @@ enum
     SOAPFpreserveSpace  = 0x0080,
     SOAPFlogmin         = 0x0100,
     SOAPFlogusermsg     = 0x0200,
-    SOAPFhttpheaders    = 0x0400
+    SOAPFhttpheaders    = 0x0400,
+    SOAPFusescontents   = 0x0800
 };
 
 struct IHThorWebServiceCallActionArg : public IHThorArg

+ 2 - 2
testing/regress/ecl/key/roxiewhitespace.xml

@@ -1,8 +1,8 @@
 <Dataset name='keepResult'>
- <Row><Dataset><Row><name><first>  Joe</first><last>  Doe</last></name><address><city>Fresno</city><state>CA</state><zipcode>11111</zipcode></address></Row></Dataset><Exception><Source></Source><Code>0</Code><Message></Message></Exception></Row>
+ <Row><Dataset><Row><name><first>  Joe</first><last>  Doe</last></name><fullname>&lt;name&gt;&lt;first&gt;  Joe&lt;/first&gt;&lt;last&gt;  Doe&lt;/last&gt;&lt;/name&gt;</fullname><address><city>Fresno</city><state>CA</state><zipcode>11111</zipcode></address></Row></Dataset><Exception><Source></Source><Code>0</Code><Message></Message></Exception></Row>
 </Dataset>
 <Dataset name='stripResult'>
- <Row><Dataset><Row><name><first>Joe</first><last>Doe</last></name><address><city>Fresno</city><state>CA</state><zipcode>11111</zipcode></address></Row></Dataset><Exception><Source></Source><Code>0</Code><Message></Message></Exception></Row>
+ <Row><Dataset><Row><name><first>Joe</first><last>Doe</last></name><fullname>&lt;name&gt;&lt;first&gt;Joe&lt;/first&gt;&lt;last&gt;Doe&lt;/last&gt;&lt;/name&gt;</fullname><address><city>Fresno</city><state>CA</state><zipcode>11111</zipcode></address></Row></Dataset><Exception><Source></Source><Code>0</Code><Message></Message></Exception></Row>
 </Dataset>
 <Dataset name='serverTooBusy'>
  <Row><serverTooBusy>3000</serverTooBusy></Row>

+ 7 - 1
testing/regress/ecl/roxiewhitespace.ecl

@@ -17,6 +17,12 @@ PersonRec := RECORD
   AddressRec Address;
 END;
 
+PersonRecOut := RECORD
+  NameRec Name;
+  string FullName {xpath('name/<>')};
+  AddressRec Address;
+END;
+
 peeps_send := DATASET([{{'  Joe  ', '  Doe  '}, {'Fresno', 'CA', 11111}}], PersonRec);
 
 roxieEchoTestRequestRecord := RECORD
@@ -30,7 +36,7 @@ exceptionRec := RECORD
 END;
 
 roxieEchoTestResponseRecord := RECORD
-  DATASET(PersonRec) Peeps {XPATH('Dataset/Row')} := DATASET([], PersonRec);
+  DATASET(PersonRecOut) Peeps {XPATH('Dataset/Row')} := DATASET([], PersonRecOut);
   exceptionRec Exception {XPATH('Exception')};
 END;