How can we use variables in wxl file [duplicate] - localization

I need to use variable in WIX localization file WIXUI_en-us.wxl.
I tried use it like this:
<String Id="Message_SomeVersionAlreadyInstalled" Overridable="yes">A another version of product $(var.InstallationVersionForGUI) is already installed</String>
But it doesn't work. And when I declared property and used it this way:
<String Id="Message_SomeVersionAlreadyInstalled" Overridable="yes">A another version of product [InstallationVersionForGUI] is already installed</String>
doesn't work either.
Where was I wrong?
Thanks for help and your time.

Localization strings are processed at link time, so you can't use $(var) preprocessor variables. Using a [property] reference is supported, as long as the place where the localization string is used supports run-time formatting (e.g., using the Formatted field type).

Your second method should work just fine. This is the same method used by the default .wxl files.
For example, in your .wxl file you would declare your string:
<String Id="Message_Foo">Foo blah blah [Property1]</String>
And in your .wxs file, you declare the property. If you wish, you can declare the property to match a WiX variable (which it sounds like you're trying to do)
<Property Id="Property1">$(var.Property1)</Property>

I was trying to get localization file to use variables. Came across this post:
There are different layers of variables in WiX (candle's preprocessor
variables, Light's WixVariables/localization variables/binder
variables, and MSI's properties). Each have different syntax and are
evaluated at different times:
Candle's preprocessor variables "$(var.VariableName)" are evaluated
when candle runs, and can be set from candle's commandline and from
"" statements. Buildtime environment
properties as well as custom variables can also be accessed similarly
(changing the "var." prefix with other values).
Light's variables accessible from the command-line are the
WixVariables, and accessing them is via the "!(wix.VariableName)"
syntax. To access your variable from your commandline, you would need
to change your String to: This build was prepared on
!(wix.BuildMachine)
If you instead need to have the BuildMachine value exist as an MSI
property at installation time (which is the "[VariableName]" syntax)
you would need to add the following to one of your wxs files in a
fragment that is already linked in:
Now, the environment variable COMPUTERNAME always has held the name of
my build machines in the past, and you can access that this way:
$(env.COMPUTERNAME). So, you can get rid of the commandline addition
to light.exe and change your wxs file like this:
<WixProperty Id="BuildMachine" Value="$(env.COMPUTERNAME)"/>

Preprocessor variables $(var.VariableName) are are processed at link time, so ideally you would use [PropertyName] which would be defined on the main Product element.
The issue sometimes is that property is not yet defined, for instance using the product name on the localization file seems not posible.
This solution was done aiming to only type the product name once given "Super product" as product name:
In case of running through visual studio extension:
Project properties -> Build -> Define variables -> "MyProductName=Super product" (No quotes)
In case of runing from cmd or some other place:
On Light.exe, add -d"MyProductName=Super product"
Into the localization .wxl file:
<String Id="Description" Overridable="yes">Description of !(wix.MyProductName)
to make it more interesting</String>
I have an aditional config file .wxi I include on other files to have some vars, for instance, here i had hardcoded the value but now it's harcoded on the variable definition and I use the given value:
<?xml version="1.0" encoding="utf-8"?>
<Include>
<!-- Define the product name preprocesor variable -->
<?define ProductName="!(wix.ProductNameDefVar)" ?>
<!-- From this point, can use the preprocesor var -->
<?define ProductName_x64="$(var.ProductName) (64bit)" ?>
<?define ProductName_x32="$(var.ProductName) (32bit)" ?>
<?define CompanyDirName = "My company name" ?>
</Include>
Finally, the place where the localization value where the localization text was not interpolating, is like this:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- Include the config file with the preprocesor var -->
<?include $(sys.CURRENTDIR)\Config.wxi?>
<!-- Main product definition -->
<Product Id="$(var.ProductCode)"
Name="$(var.ProductName)"
Language="!(loc.Language)"
Version="$(var.BuildVersion)"
Manufacturer="!(loc.Company)"
UpgradeCode="$(var.UpgradeCode)">
<!-- Package details -->
<!-- Here, Description was not interpolating -->
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine"
Platform="$(var.Platform)"
Manufacturer="!(loc.Company)"
Description="!(loc.Description)"
Keywords="!(loc.Keywords)"
Comments="!(loc.Comments)"
Languages="!(loc.Language)"
/>
[...]

Related

Unable to parse XML with multiple namespaces using tcl and tdom

I am trying to parse a XML using tcl and tdom package. I am having trouble doing this as the node I want to parse is a child to a node with multiple namespaces. How would I be able to parse the realmCode or title element? Below is what I have tried:
package require tdom
set XML {<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://www.cerner.com/cda_stylesheet/" ?>
<ClinicalDocument xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sdtc="urn:hl7-org:sdtc" xsi:schemaLocation="urn:hl7-org:v3 ../../../CDA%20R2/cda-schemas-and-samples/infrastructure/cda/CDA.xsd" classCode="DOCCLIN" moodCode="EVN">
<realmCode code="US" />
<title>Discharge Summary</title>
</ClinicalDocument>}
set nsmap {
a urn:hl7-org:v3
x http://www.w3.org/2001/XMLSchema-instance
s urn:hl7-org:sdtc
}
set doc [dom parse $XML]
set root [$doc documentElement]
set node [$root selectNodes -namespaces $nsmap "/a:ClinicalDocument/title"]
#set node [$root selectNodes "/ClinicalDocument/title"] ;# tried this as well - does not work
$doc delete
You need to specify the namespace for every level of the path, not just the root. Use
set title [$root selectNodes -namespaces $nsmap /a:ClinicalDocument/a:title]
set realm [$root selectNodes -namespaces $nsmap /a:ClinicalDocument/a:realmCode/#code]
etc.
This is more for the sake of completeness, and not necessarily recommended. You may instruct tDOM to simply ignore the namespaces. See -ignorexmlns.
Watch:
set doc [dom parse -ignorexmlns $XML]
set root [$doc documentElement]
$root selectNodes "/ClinicalDocument/title"
$root selectNodes "/ClinicalDocument/realmCode/#code"
The consequences are obvious: ambiguity.

How do I set culture for coded UI Test to get localised text from resource file?

Scenario:
We have an application with localisation capabilities for which we doing automated testing with an extensive Coded UI Test suite. The UI text reflects the user's selected main language, e.g. French.
We have a number of message assertions to check specific results, and as a result we have to cater for the localised environment.
I have started on creating the localised Resources.resx files (e.g. Resources.fr-FR.resx) and set the CurrentUICulture to fr-FR, but the English string is always retrieved. (The Properties.Resources.Culture is always null, and even if I force-set it, no success...)
Any ideas on how to achieve this or where I'm going wrong? Do I have to force-deploy the assembly with the localised text?
Thanks!
OK, so I figured this out:
For coded UI tests, all the necessary assemblies have to be in the ..\TestResults\uniqueTestInstance\Out folder. The language assemblies aren't copied here automatically, so what I've done is to add the following to my testsettings file:
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="RegressionCUIT" id="caf0f1b1-7dd7-4bbe-9920-edd664229791" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are default test settings for a local test run.</Description>
<Deployment>
<DeploymentItem filename="Resources\TestData.xml" />
<DeploymentItem filename="RegressionTesting\bin\Debug\de-DE\" outputDirectory="de-DE\" />
<DeploymentItem filename="RegressionTesting\bin\Debug\fr-FR\" outputDirectory="fr-FR\" />
</Deployment>
</TestSettings>
Note the outputDirectory attribute on the DeploymentItem.
Works brilliantly now.
Read more about file deployment here:
http://msdn.microsoft.com/en-us/library/ms182475.aspx

Replacing value in an XML file using Ant

I'm trying to automize my android build process. For that, I want to change the app name in an XML file. the code is something like this
<resources>
<string name="app_name">Realta Connections</string>
</resources>
Now I want to replace the name 'Realta Connections' by something else at build time, a name which I would give at build time. The name can be 'Realta Connections' or anything else, so I need to detect the name="app_name" and replace the content inside it. I tried looking for how to do it but couldn't find the precise way. How can I do that? Please help.
It is probaly easiest to have a fixed value, which will be replaced. This will allow the use of the replace task:
You need replacetoken/replacevalue and the Strings inside ![CDATA[]] because of the xml characters.
<replace casesensitive="false"
file="../KS.build/ivy.properties">
<replacetoken><![CDATA[<string name="app_name">Realta Connections</string>]]></replacetoken>
<replacevalue><![CDATA[<string name="app_name">Something else</string>]]></replacevalue>
</replace>
Otherwise there is no normal ant solution (repleaceregex doesn't allow nested CDATA replacements).
Links:
Ant replace task
I know this question is quite old, but here is an idea. This seems like it's not really a purely ant solution, but you can embed a script in ant using the <scriptdef> tag.
Here is a function you can use to search for something in an XML file and store the result in a property:
<scriptdef name="xpath-query" language="javascript">
<attribute name="query"/>
<attribute name="xmlfile"/>
<attribute name="property"/>
<![CDATA[
importClass(java.io.FileInputStream);
importClass(javax.xml.xpath.XPath);
importClass(javax.xml.xpath.XPathConstants);
importClass(javax.xml.xpath.XPathFactory);
importClass(org.xml.sax.InputSource);
importClass(java.lang.System);
var exp = attributes.get("query");
var filename = attributes.get("xmlfile");
var xpath = XPathFactory.newInstance().newXPath();
var input = new InputSource(new FileInputStream(filename));
var value = xpath.evaluate(exp, input, XPathConstants.STRING);
self.project.setProperty( attributes.get("property"), value );
System.out.println("Copied this value:" + value + " to this property:" + attributes.get("property"));
]]>
</scriptdef>
Then you could get the current name of the app by using the xpath-query task you just defined:
<xpath-query query='pathToResources\resources\string[#name="app_name"]' xmlFile="app.xml" property="appName" />
Then the app name will be stored in the property appName.
From there you could do regex replace on the xml file using the app name.
<replaceregexp file="app.xml" match="${appName}" replace="${newAppName}" />
The potential down-side of this particular approach is that if you have the same app name string somewhere else in the XML file the regex replace may replace something you didn't intend.
You could probably define the <scriptdef> to do the replacement rather than just storing what was found in a property, but I had this portion of code handy already.
When dealing with XML in ANT I always recommend the xmltask. For your requirement see xml task manual replace
A little Xpath knowledge won't hurt, see:
http://zvon.org/xxl/XPathTutorial/
http://www.w3schools.com/xpath/
try this code, it works for me
<target name="change-app-name">
<replaceregexp file="res/values/strings.xml" match='name="app_name"(.*)'
replace='name="app_name">Something Else<\/string>'/>
</target>

Writing a path to a property file using ant

I am writing a file path to a property file using ant property file task,below is my code snippet of ant
<propertyfile file="WeblogicDomain.properties" comment="Weblogic Properties Below">
<entry key="path" value="C:/bea"/>
</propertyfile>
In the output properties i.e.., WeblogicDomain.properties file the path varies as shown below
path=C\:/bea
i was puzzled with this, is there a solution to resolve this & place the exact path as mentioned in source code
My ant version : 1.6.5
This is how java.util.Properties works. The colon : and equals = characters are used as name value delimiters so colons are escaped when part of the key or value and not the delimiter.
See java.util.Properties.load(Reader) for more.

Ant Fileset Expansion doesn't work

I get a very confusing reaction from my ant build-file and I'm wondering whether I'm just not clever enough or this might actually be a bug.
I've got the following property set globally in my project:
<property name="lib.dir" location="lib"/>
Then I'll try to add some files out of this directory into a jar file via fileset (more than one resource):
<fileset dir="${basedir}" includes="lib/*filename*"/>
There should be (and exist) 3 different libraries, which are matched that way. However, if I try to use the following, it doesn't work and no files are included:
<fileset dir="${basedir}" includes="${lib.dir}/*filename*"/>
Note that the only differences lies in the usage of the global property. Now the simple question: why does the first version work as advertised, but the second doesn't?
Please check the actual value of "lib.dir" just before and maybe after the task that uses the "fileset" expression. Just to make sure, that it hasn't been changed accidently after you've set it globally. The <echo/> task can help.
Maybe I got the solution. The description of the locationattribute is:
Sets the property to the absolute filename of the given file. If the value of this attribute is an absolute path, it is left unchanged (with / and \ characters converted to the current platforms conventions). Otherwise it is taken as a path relative to the project's basedir and expanded.
Simply use the value attribute instead of location. Here's a test script to show the difference:
<project name="test">
<property name="test1" location="lib"></property>
<property name="test2" value="lib"></property>
<target name="target" description="description">
<echo>${test1}</echo>
<echo>${test2}</echo>
</target>
</project>
The output on my system is as follows:
Buildfile: D:\Develop\workspace-jabber\scrapbook\build.xml
target:
[echo] D:\Develop\workspace-jabber\scrapbook\lib
[echo] lib
BUILD SUCCESSFUL
Total time: 307 milliseconds
I have found a clue to the answer, but not the whole thing yet.
I runned both versions of the fileset with ant -debug and here is what happens.
In the working, not-using-property version, I get the following output:
fileset: Setup scanner in dir [pathToDir] with patternSet{ includes: [lib/*filename*] excludes: [] }
whereas in the should-be-working-but-doesn't version I get:
fileset: Setup scanner in dir [pathToDir] with patternSet{ includes: [ [pathToDir]/lib/*filename*] excludes: [] }
As you can see, ant add's the [pathToDir] in the regexp, thus searching for
[pathToDir]/[pathToDir]/lib/*filename*
which obviously doesn't exist. Problem now: how do I have to modify my version to have it working properly?
When creating the property (is it done global or in a target?), does the directory lib exist? If not, the location attribute does not work - use a value attribute instead or better define the property after creating the directory.
As indicated above, the problem was that ${lib.dir} too contained the whole path, thus searching for [pathToDir]/[pathToDir]/lib/filename.
To clip away the unwanted [pathToDir] in the ${lib.dir} property, I now used the task. I got now the following, but imho not so nice looking solution:
<basename property="lib.dir.rel" file="${lib.dir}"/>
<fileset dir="${basedir}" includes="${lib.dir.rel}/*filename*"/>
P.S.: On a second look, I found that Andreas_D also found the right reason and a good suggestion yesterday, which I must have overlooked :-/

Resources