Forum Discussion

Santhosh_P's avatar
Santhosh_P
Contributor
8 years ago

How do i find an xml node and insert one or more nodes right below that node?

Here is a sample xml:

<HomeOwnersContext xmlns="http://schemas.datacontract.org/2004/07/Homesite.Homeowners.ContextModel.Api.Context" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <DisplayOnlyData/>
<QuoteData>
<animalsBitten>false</animalsBitten>
<burglarAlarm>No</burglarAlarm>
<businessOnPremises>false</businessOnPremises>
<totalNumberOfPeople>2</totalNumberOfPeople>
</QuoteData>
<QuoteHeader>
<Channel>Direct_Web</Channel>
<FormCode>3</FormCode>
</QuoteHeader>
</HomeOwnersContext>

 

Now i want to find <burglarAlarm> node and insert the below node

<cancelledForNonPay>1</cancelledForNonPay> right below that node.

  • Here's a quick groovy script that kind of does what

    // get the request and its content content of the test
    // Adjust "TEST STEP NAME" accordingly
    
    def testRequest = context.testCase.testSteps["TEST STEP NAME"].testRequest
    def request = testRequest.requestContent;
    
    // log.info(request);
    
    // create an array of lines of the request, split by newline characters
    def splitRequest = request.split("\n");
    
    // build a new, empty request
    def newRequest = "";
    
    // loop through every line in the request that was split
    for (splitString in splitRequest)
    {
    	// if we find the line that needs replacing
    	if (splitString.contains("<burglarAlarm>No</burglarAlarm>"))
    	{
    		// find the spacing tabs of the element in question
    		def spacing = splitString.tokenize("<")[0];
    		// create a new line that exists of the elemnet searched for, a new line character, and appropriate spacing.
    		def newSplit = splitString + '\n' + spacing + "<cancelledForNonPay>1</cancelledForNonPay>" + "\n";
    		newRequest += newSplit;
    	}
    	else
    	{
    		// if the line is not the one being searched for, append the line as normal, with new line.
    		newRequest += splitString + '\n';
    	}
    }
    
    log.info(newRequest);
    
    
    // The line below, when uncommented, will overwrite the contents of test step "TEST STEP NAME"
    //testRequest.setRequestContent(newRequest);

    you want. 

  • groovyguy's avatar
    groovyguy
    8 years ago

    I believe you want to replace my line here:

     

     

    def request = testRequest.requestContent;

     

    With:

     

    def request = serialXML;

    My scriprt assumed you were using XML from a pre-existing test step. Since that is not the case, you can set it to the value you are parsing from the Excel data source. That should work for what you want.

  • nmrao's avatar
    nmrao
    Champion Level 3

    Santhosh_P,

     

    Here is the simple, better, readable and more groovified way of doing it. 

     

    This way, you will not land into trouble if the xml has namespace prefixes.

     

     

    //Pass xml string to parseText method and also declare the namespaces used in the xml
    def pxml = new XmlSlurper().parseText(xml).declareNamespace('con':'http://schemas.datacontract.org/2004/07/Homesite.Homeowners.ContextModel.Api.Context', 'xsi': 'http://www.w3.org/2001/XMLSchema-instance')
    //Add the element after burglarAlarm
    pxml.QuoteData.burglarAlarm + { con.cancelledForNonPay (1) } def output = groovy.xml.XmlUtil.serialize(pxml) log.info "Changed xml : \n $output"

     

    The above script is also available (along with xml) here in my github

     

    • groovyguy's avatar
      groovyguy
      Community Hero

      Here's a quick groovy script that kind of does what

      // get the request and its content content of the test
      // Adjust "TEST STEP NAME" accordingly
      
      def testRequest = context.testCase.testSteps["TEST STEP NAME"].testRequest
      def request = testRequest.requestContent;
      
      // log.info(request);
      
      // create an array of lines of the request, split by newline characters
      def splitRequest = request.split("\n");
      
      // build a new, empty request
      def newRequest = "";
      
      // loop through every line in the request that was split
      for (splitString in splitRequest)
      {
      	// if we find the line that needs replacing
      	if (splitString.contains("<burglarAlarm>No</burglarAlarm>"))
      	{
      		// find the spacing tabs of the element in question
      		def spacing = splitString.tokenize("<")[0];
      		// create a new line that exists of the elemnet searched for, a new line character, and appropriate spacing.
      		def newSplit = splitString + '\n' + spacing + "<cancelledForNonPay>1</cancelledForNonPay>" + "\n";
      		newRequest += newSplit;
      	}
      	else
      	{
      		// if the line is not the one being searched for, append the line as normal, with new line.
      		newRequest += splitString + '\n';
      	}
      }
      
      log.info(newRequest);
      
      
      // The line below, when uncommented, will overwrite the contents of test step "TEST STEP NAME"
      //testRequest.setRequestContent(newRequest);

      you want. 

      • Santhosh_P's avatar
        Santhosh_P
        Contributor

        Hi msiadak,

         

        Thanks for the solution. It worked! 

        I am starting to learn groovy now with Ready API!

         

        I got another question:

        I was getting an xml from the excel sheet,serializing it and putting it into the REST request to get the response but now i am adding another step:

        1> Getting xml from excel sheet(data source)

        2> Serializing it

        3> Find a node and insert a desired node right below it.

        4> Put the new xml request in the REST request to get the response.

         

        // Getting the xml and serializing it

        def stateDetailsXML = context.expand( '${DataSource#StateDetailsXML}' )
        def doc = new XmlParser().parseText(stateDetailsXML)
        def serialXML = groovy.xml.XmlUtil.serialize(doc)

         

        // Your piece of code to find and insert

        def testRequest = context.testCase.testSteps["serialXML "].testRequest
        def request = testRequest.requestContent;

        // log.info(request);

        // create an array of lines of the request, split by newline characters
        def splitRequest = request.split("\n");

         

        How do i modify the first 2 lines of your code to pass the serialized xml (serialXML) to your piece of code?

         

         

    • Santhosh_P's avatar
      Santhosh_P
      Contributor

      Thanks Sanj! 

      But i couldn't find any methods to find or insert a node