A powerful way to use the preprocessor is to substitute properties into placeholders in your XML file. Properties can be defined in an external XML file or passed on the command line.
For example if you have an application setting that contains the name of a remote server, but the name of that server changes from environment to environment, you may want to mark-up your XML like this:
---web.config---
<configuration> <appSettings> <!-- ifdef ${_xml_preprocess} --> <!-- <add key="server" value="${remoteserver}"/> --> <!-- else --> <add key="server" value="developmentserver1"/> <!-- endif --> </appSettings> </configuration>
When the XML preprocessor is processes this file it will remove the comments from the body of the "ifdef" branch, and substitute in the value of the "remoteserver" property. It will also comment out the body of the "else" branch.
In the above example you were to run the following command:
XmlPreprocess /c /i web.config /d:remoteserver=productionserver1
The processor would write out
---web.config---
<configuration> <appSettings> <add key="server" value="productionserver1"/> </appSettings> </configuration>
Another way to accomplish the same thing is to use an external settings file for each of your environments. The settings file is a simple XML document that contains a set of property/value pairs that should be substituted by the XML preprocessor. Here is what a settings file looks like:
---settingsfile.xml--- <settings> <property name="remoteserver">productionserver1<property> <property name="othersetting1">othersetting1<property> <property name="othersetting2">othersetting2<property> </settings>
To accomplish the same substitution as in the previous example using a settings file, the command line looks like this:
XmlPreprocess /c /i web.config /s settingsfile.xml
Properties can recursively resolve to other properties, this enables "global" variables in the settings file. For example:
<settings> <property name="protocol">tcp</property> <property name="interchange_uri">${protocol}://server1</property> <property name="metadata_uri">${protocol}://server2</property> <property name="dataservice_uri">${protocol}://server3</property> </settings>
This property file would be fed into the preprocessor along with the original file which looks like this:
<configuration> <!-- ifdef ${_xml_preprocess} --> <!-- <interchange>${interchange_uri}</interchange> <metadata>${metadata_uri}</metadata> <dataservice>${dataservice_uri}</dataservice> --> <!-- endif --> </configuration>
And the preprocessor would write out this:
<configuration> <interchange>tcp://server1</interchange> <metadata>tcp://server2</metadata> <dataservice>tcp://server3</dataservice> </configuration>
All property values are treated as strings with the exception of the word False (case is irrelevant). If you set a property to the value False, it will have the effect of un-defining it. There are some cases where you may actually want the literal value of "False" to be replaced. To accomplish this, enclose it in single or double quotes. The quotes will be stripped, and the value will simply be treated like any other string property.
These properties are automatically defined by the processor and can be referred to within the configuration file without having to pass anything in. All built-in properties begin with an underscore.
Property Name | Description |
---|---|
_xml_preprocess | This property will always be defined whenever a file is being processed by the Xml Preprocessor |
_dest_dir | Directory portion of destination file. Example: d:\inetpub\wwwroot\web |
_machine_name | Name of machine. Example: vmspap02caa |
_machine_id | Numeric portion of machine name. Example: 02 |
_os_platform | Machine OS platform. Example: Win32NT |
_os_version | Machine OS version. Example: 5.1.2600.0 |
_system_dir | Machine's system directory. Example: C:\WINNT\System32 |
_current_dir | Machine's current directory. Example: "C:\Installs |
_clr_version | Gets the major, minor, build, and revision numbers of the common language runtime. Example: 1.1.4322 |
_user_name | Gets the user name of the person who started the current thread. Example: EFudd |
_user_domain_name | Gets the network domain name associated with the current user. Example: MyDomain |
_user_interactive | Gets a value indicating whether the current process is running in user interactive mode. Example: True |
_system_date | System date. Example: 8/5/2003 |
_system_time | System time. Example: 9:50 AM |
_framework_dir | .NET Framework directory. Example: C:\WINNT\Microsoft.NET\Framework\v1.1.4322 |
_env_* | Environment variables. Example: _ENV_PATH contains system's path environment variable. |
Here is an example of these built-in properties:
<xml> <!-- ifdef ${_xml_preprocess} --> <!-- <entry dest_dir="${_dest_dir}" machine_name="${_machine_name}" machine_id="${_machine_id}" os_platform="${_os_platform}" os_version="${_os_version}" system_dir="${_system_dir}" current_dir="${_current_dir}" clr_version="${_clr_version}" user_name="${_user_name}" user_domain_name="${_user_domain_name}" user_interactive="${_user_interactive}" system_date="${_system_date}" system_time="${_system_time}" framework_dir="${_framework_dir}" env_number_of_processors="${_env_number_of_processors}" /> --> <!-- endif --> </xml>
When processed this file would produce something similar to this:
<xml> <entry dest_dir="C:\...\out" machine_name="MYMACHINE" machine_id="103" os_platform="Win32NT" os_version="5.1.2600.0" system_dir="C:\WINNT\System32" current_dir="C:\...\somedir" clr_version="1.1.4322" user_name="EFudd" user_domain_name="MYDOMAIN" user_interactive="True" system_date="9/12/2004" system_time="3:30 PM" framework_dir="c:\winnt\microsoft.net\framework\v1.1.4322" env_number_of_processors="1" /> </xml>
XmlPreprocess |