Forum Discussion

Alejandro59's avatar
Alejandro59
Occasional Contributor
11 months ago

String.replaceAll not working in Groovy script

I am using a file as a template in order to create new files. The template file contains "placeholders" in the form of [plc]placeholderName[plc]. I want to replace the placeholder at runtime with values as shown in the groovy script. 

However the String.replaceAll() method seems not to work (placeholders don't get replaced)

Am I missing something? 

The contents of the Template.xml are:

My groovy script is:

Thanks

  • Alejandro59 ,

    This is best case to use Template Engine feature of groovy.

    Instead of [plc]pattern[plc] => use $pattern or $variable

    In your case, variables are originalSender, finalRecipient, AP_Initiator etc

    Now the script will just look like below (only replacement part)

    import groovy.text.SimpleTemplateEngine
    import java.time.*
    //Here define what value needs to be replaced for each variable
    def binding = [originalSender: '9928:12341234A', finalRecipient: '9928:12341234B', AP_Initiator: 'POP000106', TimeStampNormalized: System.currentTimeMillis(), TimeStampUTC: Instant.now().atZone(ZoneId.of("UTC"))]
    
    def template = new SimpleTemplateEngine().createTemplate(new File('C:/Templates/Template.xml').getText('UTF-8')).make(binding)
    log.info "Updated xml : ${template.toString()}"

    By the way, you can quickly run the script here to see output.

    Also wanted to point out why your script is not working.

    [plc] - here it will find only p / l / c, but not plc

    [, ] has to be escaped i.e., \[plc\]

    Then \ has to be escaped again - so finally it will be '\\[plc\\]pattern\\[plc\\]'

    Check here how it is done.

  • ChrisAdams's avatar
    ChrisAdams
    Champion Level 3

    Got it.  You need to re-assign the variable after a replace all.

    E.g.

    templ = templ.replaceAll(........

    • Alejandro59's avatar
      Alejandro59
      Occasional Contributor

      Hi Chris,

      Still does not work :-(

      Here is the last version of the script

      String templ = new File('C:/Templates/Template.xml').getText('UTF-8')
      
      String AP_Initiator = "POP000106"
      String originalSender = "9928:12341234A"
      String finalRecipient = "9928:12341234B"
      
      log.info("AP_Initiator: [$AP_Initiator]")
      log.info("originalSender: [$originalSender]")
      log.info("finalRecipient: [$finalRecipient]")
      
      templ = templ.replaceAll("[plc]AP_Initiator[plc]", AP_Initiator)
      templ = templ.replaceAll("[plc]originalSender[plc]", originalSender)
      templ = templ.replaceAll("[plc]finalRecipient[plc]", finalRecipient)
      
      log.info("ExpandedFileContents: $templ")
      return (templ);

      and the template file

      <SPAN class="token prolog"><?xml version="1.0" encoding="UTF-8" standalone="no"?></SPAN>
      <SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>StandardBusinessDocument</SPAN> <SPAN class="token attr-name">xmlns</SPAN><SPAN class="token attr-value"><SPAN class="token punctuation attr-equals">=</SPAN><SPAN class="token punctuation">"</SPAN>http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader<SPAN class="token punctuation">"</SPAN></SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      	<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>StandardBusinessDocumentHeader</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>HeaderVersion</SPAN><SPAN class="token punctuation">></SPAN></SPAN>1.0<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>HeaderVersion</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Sender</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Identifier</SPAN> <SPAN class="token attr-name">Authority</SPAN><SPAN class="token attr-value"><SPAN class="token punctuation attr-equals">=</SPAN><SPAN class="token punctuation">"</SPAN>iso6523-actorid-upis<SPAN class="token punctuation">"</SPAN></SPAN><SPAN class="token punctuation">></SPAN></SPAN>[plc]originalSender[plc]<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Identifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Sender</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Receiver</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Identifier</SPAN> <SPAN class="token attr-name">Authority</SPAN><SPAN class="token attr-value"><SPAN class="token punctuation attr-equals">=</SPAN><SPAN class="token punctuation">"</SPAN>iso6523-actorid-upis<SPAN class="token punctuation">"</SPAN></SPAN><SPAN class="token punctuation">></SPAN></SPAN>[plc]finalRecipient[plc]<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Identifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Receiver</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>DocumentIdentification</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Standard</SPAN><SPAN class="token punctuation">></SPAN></SPAN>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Standard</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>TypeVersion</SPAN><SPAN class="token punctuation">></SPAN></SPAN>2.1<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>TypeVersion</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>[plc]AP_Initiator[plc]-[plc]TimeStampNormalized[plc]<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>Invoice<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>CreationDateAndTime</SPAN><SPAN class="token punctuation">></SPAN></SPAN>[plc]TimeStampUTC[plc]<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>CreationDateAndTime</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>DocumentIdentification</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>BusinessScope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>DOCUMENTID<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>PROCESSID<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>urn:www.cenbii.eu:profile:bii05:ver2.0<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>COUNTRY_C1<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Type</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      				<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"><</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>CY<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>InstanceIdentifier</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      			<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>Scope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      		<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>BusinessScope</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
      	<SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>StandardBusinessDocumentHeader</SPAN><SPAN class="token punctuation">></SPAN></SPAN>
       <SPAN class="token tag"><SPAN class="token tag"><SPAN class="token punctuation"></</SPAN>StandardBusinessDocument</SPAN><SPAN class="token punctuation">></SPAN></SPAN>

      Since time is running out I am implementing a workaround outside ReadyAPI.

      Anyway, many thanks for your prompt support; appreciated!

      Best Regards

      • Alejandro59's avatar
        Alejandro59
        Occasional Contributor

        The template in a better form:

        <?xml version="1.0" encoding="UTF-8" standalone="no"?>
        <StandardBusinessDocument xmlns="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader">
        	<StandardBusinessDocumentHeader>
        		<HeaderVersion>1.0</HeaderVersion>
        		<Sender>
        			<Identifier Authority="iso6523-actorid-upis">[plc]originalSender[plc]</Identifier>
        		</Sender>
        		<Receiver>
        			<Identifier Authority="iso6523-actorid-upis">[plc]finalRecipient[plc]</Identifier>
        		</Receiver>
        		<DocumentIdentification>
        			<Standard>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2</Standard>
        			<TypeVersion>2.1</TypeVersion>
        			<InstanceIdentifier>[plc]AP_Initiator[plc]-[plc]TimeStampNormalized[plc]</InstanceIdentifier>
        			<Type>Invoice</Type>
        			<CreationDateAndTime>[plc]TimeStampUTC[plc]</CreationDateAndTime>
        		</DocumentIdentification>
        		<BusinessScope>
        			<Scope>
        				<Type>DOCUMENTID</Type>
        				<InstanceIdentifier>urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1</InstanceIdentifier>
        			</Scope>
        			<Scope>
        				<Type>PROCESSID</Type>
        				<InstanceIdentifier>urn:www.cenbii.eu:profile:bii05:ver2.0</InstanceIdentifier>
        			</Scope>
        			<Scope>
        				<Type>COUNTRY_C1</Type>
        				<InstanceIdentifier>CY</InstanceIdentifier>
        			</Scope>
        		</BusinessScope>
        	</StandardBusinessDocumentHeader>
         </StandardBusinessDocument>
  • ChrisAdams's avatar
    ChrisAdams
    Champion Level 3

    Hi,

    I do something similar, but I tend to 'pull' the edited version into the step that makes the request rather than your approach to 'push'.

    Your script seems sound or is at least until line 15.  I guess the log statement shows the replace all has worked.

    My suggestion....

    • comment out lines 16 onwards.
    • After line 15, create a new line 16 containing...   return templ; or might be return (templ);
    • In the step that actually makes the API request go to the payload panel and empty it.
    • Then, in the same panel, do a mouse right-click and a context menu pops up.
    • Select 'get data' and pick the script result option for the Groovy step that does the replace. 

     

    • Alejandro59's avatar
      Alejandro59
      Occasional Contributor

      Hi Chris,

      Thanks for your response.

      Did as suggested but the result is the same. The script returns the "template" with the placeholders NOT replaced.

      Regards

      • ChrisAdams's avatar
        ChrisAdams
        Champion Level 3

        OK, going back a step, does the log.info on line 15 actually show the expected content or is still the unreplaced version?

  • nmrao's avatar
    nmrao
    Champion Level 3

    Alejandro59 ,

    This is best case to use Template Engine feature of groovy.

    Instead of [plc]pattern[plc] => use $pattern or $variable

    In your case, variables are originalSender, finalRecipient, AP_Initiator etc

    Now the script will just look like below (only replacement part)

    import groovy.text.SimpleTemplateEngine
    import java.time.*
    //Here define what value needs to be replaced for each variable
    def binding = [originalSender: '9928:12341234A', finalRecipient: '9928:12341234B', AP_Initiator: 'POP000106', TimeStampNormalized: System.currentTimeMillis(), TimeStampUTC: Instant.now().atZone(ZoneId.of("UTC"))]
    
    def template = new SimpleTemplateEngine().createTemplate(new File('C:/Templates/Template.xml').getText('UTF-8')).make(binding)
    log.info "Updated xml : ${template.toString()}"

    By the way, you can quickly run the script here to see output.

    Also wanted to point out why your script is not working.

    [plc] - here it will find only p / l / c, but not plc

    [, ] has to be escaped i.e., \[plc\]

    Then \ has to be escaped again - so finally it will be '\\[plc\\]pattern\\[plc\\]'

    Check here how it is done.

      • nmrao's avatar
        nmrao
        Champion Level 3

        Glad, it helped.

        Template engine is more simple and elegant in this context. I understand if you can't change the template to suit template engine.

      • nmrao's avatar
        nmrao
        Champion Level 3

        We all learn over time.

        replace or replaceAll is better when single string is to be replaced and direct string. When it has special characters like in this case, it is tricky and don't understand what is happening though we seem to be correct.

        Template Engine is designed for multiple replaces seamlessly and fits into language , simple to use. If you notice the binding, some uses string mapping and some uses programming constructs while replacing such as dates in this case. And the transformation is done in single statement. All we need to do is to create template and binding.