Обычно при использовании веб-службы SOAP от ColdFusion вы используете <cfinvoke>
, и все возвращается в исходном формате.
Однако, особенно при использовании ASPВеб-сервисы .NET ASMX, я обнаружил, что возвращенный XML и парсер ColdFusion не всегда играют хорошо;поэтому я склонен выполнять обработку вручную.
Этот код взят из метода, который я написал для вызова API.Сначала сделайте HTTP-запрос вручную:
<cftry>
<cfhttp
url="#wsLocation#"
result="local.wsResult"
method="post"
timeout="#variables.timeout#"
throwonerror="true"
>
<cfhttpparam type="formfield" name="inputName" value="inputValue" />
<cfhttpparam type="formfield" name="inputName" value="inputValue" />
<cfhttpparam type="formfield" name="inputName" value="inputValue" />
</cfhttp>
Затем проверьте наличие общих ошибок: (вы можете столкнуться с некоторыми из них / все-из-за-ничего-больше)
<cfif trim(local.wsResult.fileContent) eq "Connection Timeout">
<cfthrow message="Request timeout while connecting to .Net API" detail="#local.wsResult.statusCode#" />
</cfif>
<cfif not isXML(local.wsResult.FileContent)>
<cfthrow message="ASP.NET WS did not return valid XML." detail="#local.wsResult.FileContent#" />
</cfif>
Затем проанализируйте возвращенный xml и верните только ту часть, которая вас интересует:
<cfset local.wsResponse = xmlParse(local.wsResult.Filecontent) />
<cfset local.rspContainer = local.wsResponse['soap:envelope']['soap:body'].BillingResponse.BillingResult />
<cfcatch>
<cfset local.arguments = arguments />
<cfset errorEmail(cfcatch, local) />
<cfreturn "" />
</cfcatch>
</cftry>
<cfreturn local.rspContainer />
Это вернет узел <BillingResponse>
и все, что внутри него.
Затем вам нужно разобрать это для данных, которые вам нужны.Вы можете сделать это с помощью выражений XPath и функции XMLSearch
, или, если данные просты, просто захватите их вручную.
DiffGram xml, на который вы ссылаетесь, вероятно, потому что вы возвращаетеобъект DataTable в вашем .Net коде.Вот как я справляюсь с этим в ColdFusion:
dataContainer = apiRequest(whatever); //calls the method above
Сначала убедитесь, что есть дочерние элементы для получения:
local.emptySet = QueryNew("GivenName,Surname,FileAs,CompanyName");
if (not structKeyExists(local.dataContainer, "DocumentElement")){ return local.emptySet; }
//emptySet is whatever object you're converting the xml into, only with no data, so
//maybe an empty query or structure or something.
Затем получите массив дочерних элементов:
local.items = local.dataContainer.DocumentElement.XmlChildren;
В моем случае я создаю запрос, поэтому я добавляю в запрос достаточное количество строк для хранения всех данных:
//create enough rows in the query to store the contact data
QueryAddRow(local.emptySet, arrayLen(local.items));
Затем зацикливаем каждый узел в массиве дочерних элементов,копирование значения в запрос.Переменная local.fieldList
представляет собой список узлов xml внутри каждой строки в вашей DataTable, и она будет использовать список для получения каждого поля.Внешний цикл выполняет итерацию по строкам в DataTable, а внутренний цикл выполняет итерацию по столбцам в строке.Я много вычеркнул из своего списка, чтобы сохранить код относительно небольшим, но проблем с его увеличением не возникает.
//popuplate the query
for (local.i = 1; local.i lte arrayLen(local.items); local.i = local.i + 1){
local.fieldList = "GivenName,Surname,FileAs,CompanyName";
for (local.j = 1; local.j lte listLen(local.fieldList); local.j = local.j + 1){
local.key = listGetAt(local.fieldList, local.j);
if (structKeyExists(local.items[local.i], local.key)){
QuerySetCell(local.emptySet, local.key, local.items[local.i][local.key].XmlText, local.i);
}
}
}
return local.emptySet;
О, и это также предполагает, что имена полей в вашем DataTable являютсяточно так же, как имена столбцов в запросе, в который они копируются.