Groovy HTTPBuilder SOAP-ответ не анализируется должным образом - PullRequest
0 голосов
/ 20 октября 2011

Я не понимаю, почему XmlSlurper, по-видимому, не работает с результатом.

import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*


def String WSDL_URL = ...
def http = new HTTPBuilder( WSDL_URL , ContentType.XML )
String soapEnvelope = 
          """<?xml version="1.0" encoding="utf-8"?>
        <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                         xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                         xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
          <soap12:Body>
            <GetTerritories xmlns="...">
              <State>AZ</State>
              <ZipCode>85203</ZipCode>
            </GetTerritories>
          </soap12:Body>
        </soap12:Envelope>"""
        http.request( POST, XML ) {
             headers."Content-Type" = "application/soap+xml; charset=utf-8"
             headers."Accept" = "application/soap+xml; charset=utf-8"
             body = soapEnvelope

            response.success = { resp, xml ->     
                println "XML was ${xml}"
                println "Territories were ${xml.Territories}"
                println "State were ${xml.Territories.State}"
                println "City was ${xml.Territories.Territory.City}"
                println "County was ${xml.Territories.Territory.County}"
            }

            response.failure = { resp, xml ->
                xml
            }
        } 

приводит к

XML was <Territories><State>AZ</State><ZipCode>85203</ZipCode><Territory><City>Mesa</City><County>Maricopa</County>...</Territory></Territories>
Territories were 
State were 
City was 
County was 

ОБНОВЛЕНИЕ: Благодаря пониманию Джона Вагенляйтнера, я сделал немногобольше копания.

Когда я добавляю это утверждение, я вижу проблему:

assert "Territories" == xml.name()
                     |  |   |
                     |  |   Envelope
                     |  <Territories><State>AZ</State><ZipCode>85203</ZipCode</Territories>
                     false

Изменение параметров запроса с POST, XML на POST, TEXT показывает:

XML was <?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 
      xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <soap:Body>
        <GetTerritoriesResponse xmlns="...">
            <GetTerritoriesResult>&lt;Territories&gt;&lt;State&gt;AZ&lt;/State&gt;&lt;ZipCode&gt;85203&lt;/ZipCode&gt;&lt;Territory&gt;&lt;City&gt;Mesa&lt;/City&gt;&lt;County&gt;Maricopa&lt;/County&gt;...&lt;/Territory&gt;&lt;/Territories&gt;
            </GetTerritoriesResult>
        </GetTerritoriesResponse>
    </soap:Body>
</soap:Envelope>

...

Таким образом, похоже, что XmlSlurper, когда переменная печатается, отбрасывает SOAP и оценивает самый внутренний узел (), фактически не переходя к этому узлу.Это ожидаемое поведение?

Мне не удалось найти более совершенный и современный SOAP-вызов и анализ с использованием httpBuilder, поэтому я предположил, что XML будет правильным типом контента.Но, похоже, мне просто нужно принять ТЕКСТ и разобрать тело самому, что кажется хромым.Есть ли лучший способ обработки ответов SOAP с помощью httpBuilder?

1 Ответ

1 голос
/ 20 октября 2011

Я бы порекомендовал распечатать необработанный текст ответа:

println "XML was ${resp.data.text}"

Если предположить, что напечатанная строка XML соответствует вашим ожиданиям (хотя это и странно, так как нет узлов Envelope или Body), тогда вам следуетвозможность удалить Territories из ваших ссылок на XML.При синтаксическом анализе с помощью XmlSlurper корневым узлом является GPathResult.

assert "Territories" == xml.name()
println "State were ${xml.State.text()}"
println "City were ${xml.Territory.City.text()}"
println "County were ${xml.Territory.County.text()}"

Также просто хотел указать, что тип носителя SOAP 1.2 - это «application / soap + xml».

ОБНОВЛЕНИЕ:

Таким образом, похоже, что XmlSlurper, когда переменная выводится на печать, отбрасывает SOAP и оценивает самый внутренний узел (), фактически не переходя к этому узлу,Это ожидаемое поведение?

Да, метод toString () для GPathResult просто печатает все текстовые узлы, а не фактические элементы или атрибуты.С HTTPBuilder вы можете распечатать необработанный текст ответа, используя:

println resp.data.text

Мне не удалось найти более совершенный и современный вызов SOAP и выполнить анализ с использованием httpBuilder, поэтому я предположил, что XML будетправильный тип контента.Но, похоже, мне просто нужно принять ТЕКСТ и разобрать тело самому, что кажется хромым.Есть ли лучший способ обработки ответов SOAP с помощью httpBuilder?

ContentType.XML в порядке, проблема заключается в том, как ответ SOAP позволяетвеб-сервис возвращается.Веб-служба отправляет обратно результаты Territories в виде закодированной строки в элементе GetTerritoriesResult , а не как часть фактического XML-ответаэтот HTTPBuilder автоматически анализирует вас (это не проблема с тем, как HTTPBuilder обрабатывает его).Поскольку данные, которые вам действительно нужны, находятся в этой зашифрованной строке, вам необходимо проанализировать текстовый узел GetTerritoriesResult самостоятельно.

response.success = { resp, xml ->     
    println "XML was ${resp.data.text}"
    def territories = new XmlSlurper().parseText(
        xml.Body.GetTerritoriesResponse.GetTerritoriesResult.text()
    )
    println "State were ${territories.State}"
    println "City was ${territories.Territory.City}"
    println "County was ${territories.Territory.County}"
}
...