I do believe that only works for Windows applications, not web applications, 
but I could be wrong.


Brian Wilson
Programmer Analyst, Associate
Department of Human Resources
Email: brian.wil...@dhr.alabama.gov<mailto:brian.wil...@dhr.alabama.gov>


From: Bob Archer [mailto:bob.arc...@amsi.com]
Sent: Monday, August 29, 2011 2:52 PM
To: Scott Pennington; nant-users@lists.sourceforge.net
Subject: Re: [NAnt-users] xmlpoke vs token replace for Config Files

You might want to take a look at slow cheetah.

http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx

BOb


From: Scott Pennington [mailto:spenning...@prosper.com]
Sent: Monday, August 29, 2011 2:50 PM
To: nant-users@lists.sourceforge.net
Subject: [NAnt-users] xmlpoke vs token replace for Config Files

This is a long post.  The simple question is what methods have you chosen to 
maintain config files when deployed to multiple environments?


I am in the process of reworking a set of build, package, install NAnt scripts 
that mainly use Token Replace and I am trying to decide if it is better to 
switch to a method I have used before of XMLPoke.

The current method is to take the existing config file and replace the 
AppSettings with a version of the AppSettings that have all of the values 
replaced as tokens with the token name being the same name as the key.  When 
the script comes to the part where it needs to set the values for the 
environment it will pass the each config file to a single target.  In the 
target it has all of the replacestokens for each file seperated by an if in the

<replacetokens if="${output.config.name == 'MailerService.exe.config'}">

and then it sets the tokens for that specific config file.  Once it has gone 
through all the ones it know s about it has a section that it tries to catch 
the ones that might be there.

I see some good things and bad things with this method.

Bad
1)  I don't really like the Target being the all in one place for each config 
file (this could be fixed with refactoring)
2) Lots of repeated values (this could be fixed with refactoring)
3) If new appsettings are added the token will need to be added.

Good
1)  Each config could have unique values
2)  When a appsetting is missed the build will fail allowing new appsettings to 
not be forgotten
3) it is already built
4) The name of the token is always the name of the appsetting


A method I came up with to handle config files would work here but I am not 
sure it is worth the effort in the long run.  I will share the basic method 
below.

There are 4 files.
1) Run.build is where you will be determining what values need to be set in the 
config file and what config file to work with
2) config.helper.build is where the actual replacement happens.
3) config.xpath.build is where the actual xpaths of where the specific item is 
located in the config file
4) env.properties.build is where the specific values are set for each value.  
This is the file you would be changing for each environment.  change all you 
need in one file.

The over view of the process is that you create a file that holds all the xpath 
to each of the settings.  if the values need to be different in different 
config files for the same key and xpath you will need to create a unique 
property/target combo name that is unique.  Each item that you want to set in a 
config file has a property and a target of the same name.  This way you can 
easily find the property and xpath match.  For each time you want to set the 
property in your config file you simply need to set the config file you want to 
change and call the target of the item you want to replace.  This is really 
clean and easy to read.


Bad
1) need to track down all the valid XPaths
2) need seperate property / target when the same xpath and different values are 
needed
3) could miss values set for keys that are not specifically called out leaving 
dev or other values in the deployed version.

Good
1) easy to see what all the values are
2) know specifically what is being replaced for each config file
3) one file for each environment
4) no need to create and replace tokens
5) can replace any attribute in the config file as long as you can create an 
XPath to it.
6) more likely to reuse properties for configs



Run.build
<project name="SupportConfig" default="config.update">
  <property name="property.values.file" value="env.properties.build" />
  <include buildfile="${property.values.file}" />
  <include buildfile="config.xpath.build" />
  <include buildfile="config.helper.build" />

  <target name="support.config.update">
    <property name="this.config.file" 
value="${Depot_Path}\projects\Support\web.config" />
    <call target="PUBLIC_SITE_URL" />
    <call target="PUBLIC_SITE_SECURE_URL" />
   </target>
</project>

config.helper.build
<project name="config.helper">
  <property name="this.config.file" value="" />
  <property name="this.xpath" value="" />
  <property name="this.value" value="" />
  <target name="config.poke">
    <if test="${file::exists(this.config.file)}">
      <xmlpoke file="${this.config.file}" value="${this.value}" 
xpath="${this.xpath}" />
      <echo message="Poked ${this.config.file}.  Changed value @ ${this.xpath} 
to ${this.value}" />
    </if>

    <if test="${not file::exists(this.config.file)}">
      <echo message="The version file ${this.config.file} doesn't exist!" />
    </if>
   </target>
</project>

config.xpath.build
<project name="config.xpath">
  <target name="PUBLIC_SITE_URL">
    <property name="this.xpath" 
value="/configuration/appSettings/add[@key='PUBLIC_SITE_URL']/@value" />
    <property name="this.value" value=" ${target::get-current-target()}" />
    <call target="config.poke" />
  </target>
  <target name="PUBLIC_SITE_SECURE_URL">
    <property name="this.xpath" 
value="/configuration/appSettings/add[@key='PUBLIC_SITE_SECURE_URL']/@value" />
    <property name="this.value" value="${target::get-current-target()}" />
    <call target="config.poke" />
  </target>
</project>

env.properties.build
<project name="env.properties">
  <property name="Platform_Domain"                                     
value="wwww.mydomain.com" />
  <property name="Depot_Path"                                          
value="c:\perforce-depot\Branch" />
  <property name="PUBLIC_SITE_URL"                                     
value="http://${Platform_Domain}<http://$%7bPlatform_Domain%7d>"/>
  <property name="PUBLIC_SITE_SECURE_URL"                              
value="https://${Platform_Domain}<https://$%7bPlatform_Domain%7d>"/>
</project>




Scott Pennington
Senior Software Engineer
Prosper Marketplace, Inc.
111 Sutter Street, 22nd Floor
San Francisco CA 94104
www.prosper.com<http://www.prosper.com/>


------------------------------------------------------------------------------
Special Offer -- Download ArcSight Logger for FREE!
Finally, a world-class log management solution at an even better 
price-free! And you'll get a free "Love Thy Logs" t-shirt when you
download Logger. Secure your free ArcSight Logger TODAY!
http://p.sf.net/sfu/arcsisghtdev2dev
_______________________________________________
NAnt-users mailing list
NAnt-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nant-users

Reply via email to