2016-06-22 6 views
2

セットアップ:SOAP UI 5.2.0。、XMLを生成するためのGroovyステップ。 サンプルXMLに配置するXPathのようなノードの場所と新しい値を含むCSVを読み込む必要があります。 Body.GetWeather[1].CityNamexpathのxpath内の値を繰り返すGroovyリファレンス(補間誤用?)

def node = xml 
key.split("\\.").each { 
    node = node."${it}" 
} 
で、それが誤解するよう 私たちのXMLが含まれている要素を繰り返し、使用可能ではない「[1]」:
次の答えのコードの最後のバージョンは完全に罰金我々の目標に合う: Groovy replace node values in xml with xpath
唯一の問題は、

理想的には、Body.GetWeather[CountryName="Africa"].CityNameのようなものも使用する必要があります。
XMLParserも試してみましたが、構文を試しました(下記参照)。私はGroovyが新しく、何か不足しているかもしれません。 問題を別の方法で解決する必要があるかどうかを教えてください。以下

第3実施例に記載さ実際の問題である:

// reading XML 
def myInputXML = ''' 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <web:GetWeather xmlns:web="http://www.webserviceX.NET"> 
      <web:CityName>Cairo</web:CityName> 
      <web:CountryName>Africa</web:CountryName> 
     </web:GetWeather> 
     <web:GetWeather xmlns:web="http://www.webserviceX.NET"> 
      <web:CityName>Heidelberg</web:CityName> 
      <web:CountryName>Germany</web:CountryName> 
     </web:GetWeather> 
     <web:GetWeather xmlns:web="http://www.webserviceX.NET"> 
      <web:CityName>Strasbourg</web:CityName> 
      <web:CountryName>France</web:CountryName> 
     </web:GetWeather> 
    </soapenv:Body> 
</soapenv:Envelope> 
''' 
def xml = new XmlSlurper().parseText(myInputXML) 
// Example 1 // 
def GetAllCities = xml.Body.GetWeather.CityName 
log.info ("Example 1: "+GetAllCities.text()) // references all 3 CityName nodes, prints out - CairoHeidelbergStrasbourg 
// Example 2 // 
def Get2ndCity = xml.Body.GetWeather[1].CityName 
log.info ("Example 2: "+Get2ndCity.text()) // references 2nd node, prints out - Heidelberg 
// Example 3 // 
def tmpNode1 = "Body" 
def tmpNode2 = "GetWeather[0]" 
    // This problem is with interpolation of GetWeather[0]. tmpNode2 = "GetWeather" would work as Example 1 
def tmpNode3 = "CityName" 
def GetFirstCity = xml."${tmpNode1}"."${tmpNode2}"."${tmpNode3}" 
log.info ("Example 3: "+GetFirstCity.text()) // prints "" - WHY? 
log.info ("Interpolation of tmpNodes 1, 2, 3:") 
log.info ("${tmpNode1}") // prints Body 
log.info ("${tmpNode2}") // prints GetWeather[0] 
log.info ("${tmpNode3}") // prints CityName 

P.S.私の例が実際の問題と無関係である場合の謝罪、私はそれらが幾分役立つと思ったが、目的は反復要素をサポートするために上記のstackoverflow答えを改善することである。

答えて

1

この場合、スクリプトを修正するだけでよい場合は、次のように変更して期待どおりのデータを取得してください。

// Example 3 // 
def tmpNode1 = "Body" 
def tmpNode2 = "GetWeather[0]" 
    // This problem is with interpolation of GetWeather[0]. tmpNode2 = "GetWeather" would work as Example 1 
def tmpNode3 = "CityName" 
def GetFirstCity = xml."${tmpNode1}"."${tmpNode2}"."${tmpNode3}" 
log.info ("Example 3: "+GetFirstCity.text()) // prints "" - 

// Example 3 // def tmpNode1 = "Body" //removed index from here def tmpNode2 = "GetWeather" def tmpNode3 = "CityName" //Added index here in below def GetFirstCity = xml."${tmpNode1}"."${tmpNode2}"[0]."${tmpNode3}" log.info ("Example 3: "+GetFirstCity.text()) 

エレガントなアプローチから

変更:

はしかし、ここで私はcsvファイルからの要求を生成する方法があります。 xmlテンプレートは含まれておらず、代わりにリクエストxmlStreamingMarkupBuilderで作成してください。これはエレガントな方法で柔軟なためです。また、csvにはデータだけが含まれているため、非常に読みやすくなります。あなたが言及したようなxpath'sはありません。

以下のスクリプトはこの非常に良いライブラリgroovycsv(これはopencsvに依存します)を使用しています。

  • jarファイルをダウンロードします。
  • SOAPUI_HOME/bin/extディレクトリにコピーします。
  • soapuiを再起動します。ここで

は、CSVファイルに基づいて要求XMLを構築するスクリプトです:

import groovy.xml.* 
import static com.xlson.groovycsv.CsvParser.parseCsv 
//closure which builds the request based on the data provided 
def requestBuilder = { csvData -> 
    def builder = new StreamingMarkupBuilder() 
    builder.encoding = 'UTF-8' 
    def soapRequest = builder.bind { 
     mkp.xmlDeclaration() 
     namespaces << [soap: 'http://schemas.xmlsoap.org/soap/envelope/', 
          web : 'http://www.webserviceX.NET'] 
     soap.Envelope { 
      soap.Header{} 
      soap.Body { 
       //loop thru the rows 
       csvData.each { row -> 
        //create GetWeather element for each row 
        web.GetWeather{ 
         web.CityName(row.CityName) 
         web.CountryName(row.CountryName) 
        } 
       } 
      } 
     } 
    } 
} 
//Used fixed csv data. But you can replace it with reading from file too 
def csv = '''CityName,CountryName 
Cairo,Africa 
Heidelberg,Germany 
Strasbourg,France''' 
/** 
//use this to read from file and remove above statement 
def csv = new File('/absolute/csv/file/path').text 
**/ 
//parse the csv using groovy csv library 
def data = parseCsv(csv) 
//call the above closure get the request and serialize it to string 
def request = XmlUtil.serialize(requestBuilder(data)) 
log.info request 

あなたの代わりにlog.infoprint requestを使用して、それはかなりプリントのXMLが表示されます(あなたが開始する必要がありますコマンドラインSOAPUI_HOME/bin/soapuiのsoapuiバット) enter image description here

+0

ありがとうございます。私は最初の提案を例3でテストしましたが、それは私のためには機能しませんでした...そのようなものや類似のものがうまくいくならば、私は既存の設定を使うことができます。 – Zaplatki

+0

あなたが知っている、何が間違っている可能性がありますか?Groovyのバージョン/誤植ですか? 2番目の提案について: 私はopenCSVを使用するスクリプトをリファクタリングしますが、サンプルXMLを使用せずにXMLを作成することは、私たちの目標に役立ちません:XMLの何百もの要素があります。同じ場所ではなく、さまざまなXMLファイルにあります。私たちはこれらのXPathのような場所を使用する必要があり、繰り返しの要素の異なるインスタントに異なる値を設定できないという限界が現在の主な問題です。 – Zaplatki

+0

@Zaplatki、実際に私は誤って入力ミスを修正しました。 $ {tmpNode1} "。" $ {tmpNode2} "[0]。" $ tmpNode3 "'。再試行してください。 – Rao