Веб-сервис cfcomponent - получение атрибутов SOAP

Вот пример SOAP-запроса:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ws="http://ws_test">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:testService a1="a1" a2="a2">
         <ws:e1>e1</ws:e1>
         <ws:e2>e2</ws:e2>
      </ws:testService>
   </soapenv:Body>
</soapenv:Envelope>

А вот мой пример веб-службы cfc:

<cfcomponent style="document" wsversion = 1>
    <cffunction name="testService" returntype="String" access="remote" >
        <cfargument type="string" name="e1"/>
        <cfargument type="string" name="e2"/>

        <!--- Missing: code to extract a1 and a2 --->   

        <cfreturn "#e1# #e2#">
    </cffunction>
</cfcomponent>

Я новичок в Coldfusion и веб-сервисе и не знаю, как извлечь атрибуты a1 и a2 из <testService>, погуглил, но не могу найти никаких ссылок. Есть идеи?

=== Редактировать ===

Думаю, это будет полезно, если я добавлю определение типа:

<complexType name="testServiceType">
    <sequence>
        <element name="e1" type="string"></element>
        <element name="e2" type="string"></element>
    </sequence>
    <attribute name="a1" type="string"/>
    <attribute name="a2" type="string"/>
</complexType>

Обратите внимание, что, хотя это мой тестовый веб-сервис, но он основан на схеме данных, предоставленной нашим партнером, это означает, что мой веб-сервис должен соответствовать этому.

=== Разрешение ===

Исходя из ответа Джерри, это то, что я в итоге сделал:

<cfcomponent style="document" wsversion = 1>
    <cffunction name="testService" returntype="String" access="remote" >
        <cfargument type="string" name="e1"/>
        <cfargument type="string" name="e2"/>

        <cfset soapReq = getSOAPRequest()>
        <cfset soapXML = xmlParse(soapReq)>
        <cfset attributes = soapXML.Envelope.body.XmlChildren[1].XmlAttributes>

        <cfset a1 = attributes.a1>
        <cfset a2 = attributes.a2>

        <cfreturn "#e1# #e2# #a1# #a2#">
    </cffunction>
</cfcomponent>

3 ответа

Решение

Исходя из вашего комментария, я думаю, что вам нужно getSoapRequest(), а затем проанализировать его, используя код из ответа, данного keshav-jha

<cfcomponent style="document" wsversion = 1>

    <cffunction name="testService" returntype="String" access="remote" >
        <cfargument type="string" name="e1"/>
        <cfargument type="string" name="e2"/>
        <cfscript>
            soapReq=GetSOAPRequest();
            soapXML=xmlParse(soapReq);
            bodyAttributes = {
                a1:soapXML.Envelope.body.XmlChildren[1].XmlAttributes.a1
                ,a2:soapXML.Envelope.body.XmlChildren[1].XmlAttributes.a2
            };
            return serializejson(bodyAttributes);
        </cfscript>

    </cffunction>
</cfcomponent>

Вам просто нужно проанализировать ваш XML и затем получить значения a1 и a2

<cfsavecontent variable="myXML" >
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws_test">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:testService a1="a1" a2="a2">
         <ws:e1>e1</ws:e1>
         <ws:e2>e2</ws:e2>
      </ws:testService>
   </soapenv:Body>
</soapenv:Envelope>
</cfsavecontent>
 <cfset parXML = xmlParse(myXML) />
<cfdump var="#parXML.Envelope.body.XmlChildren[1].XmlAttributes.a1#">

Если вы создаете веб-сервис, то вы полностью контролируете, как он используется. В этом случае a1 и a2 никогда не передаются в CFC для обработки. Так что, если они имеют значение, вы можете установить их в качестве параметров, таких как e1 и e2.

SoapUI- один из лучших инструментов, которые я когда-либо использовал для понимания и использования веб-сервисов. Если вы создадите example.cfc и укажете на него SOAPUI, вы получите XML-запрос, который выглядит следующим образом:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.stack">
   <soapenv:Header/>
   <soapenv:Body>
      <soap:testService>
         <soap:e1>e1</soap:e1>
         <soap:e2>e2</soap:e2>
      </soap:testService>
   </soapenv:Body>
</soapenv:Envelope>

Если вы хотите обработать a1 и a2, нет причин не обрабатывать их как обычные аргументы.

Таким образом, вы можете сделать CFC, который выглядит следующим образом:

<cfcomponent style="document" wsversion = 1>

    <cffunction name="testService" returntype="String" access="remote" >
        <cfargument type="string" name="a1"/>
        <cfargument type="string" name="a2"/>
        <cfargument type="string" name="e1"/>
        <cfargument type="string" name="e2"/>


        <cfset var ret=serializeJSON(arguments) />
        <cfreturn "#ret#">
    </cffunction>
</cfcomponent>

И если вы укажете на SOAPUI, он сгенерирует конверт SOAP, который выглядит следующим образом:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.stack">
   <soapenv:Header/>
   <soapenv:Body>
      <soap:testService>
         <soap:a1>?</soap:a1>
         <soap:a2>?</soap:a2>
         <soap:e1>?</soap:e1>
         <soap:e2>?</soap:e2>
      </soap:testService>
   </soapenv:Body>
</soapenv:Envelope>
Другие вопросы по тегам