我有以下wix包括 VersionFile.wxi
<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define ProductVersionMajor = "1" ?>
<?define ProductVersionMinor = "00" ?>
<?define ProductName= "MyProduct" ?>
<?define UpgradeCode = "myUpgradeCode" ?>
</Include>
现在我想得到ProductVersionMajor使用XmlPeek和XPath查询作为“1”或ProductName“MyProduct”(不带引号)。使用以下代码
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Test">
<XmlPeek XmlInputPath="VersionFile.wxi"
Query="//processing-instruction('define')[starts-with(., "ProductVersionMajor =")]">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
<XmlPeek XmlInputPath="VersionFile.wxi"
Query="//processing-instruction('define')[starts-with(., "ProductVersionMajor=")]">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
<Message Text="@(Peeked)"/>
</Target>
</Project>
我已经把它归结为
<?define ProductVersionMajor = "1" ?>
但目标是
1
任何帮助如何调整XPath查询高度赞赏。另外,使用占位符“ProductVersionMajor * =”而不是两次使用XmlPeek会很棒。
<XmlPeek XmlInputPath="ProductVersion.wxi"
Query="substring-before(substring-after(//processing-instruction("define")[starts-with(., "ProductVersionMajor=")],"),")">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
不幸的是只产生了一个
错误MSB3734:XPath查询“substring-before(substring-after(// processing-instruction(”define“)[starts-with(。,”ProductVersionMajor =“)],”),“)”无法加载。 'substring-before(substring-after(// processing-instruction(“define”)[starts-with(。,“ProductVersionMajor =”)],“),”)'有一个无效的令牌。
假设XmlPeek可能需要更多自定义XPath语法?
是。也尝试过。现在也试过了
Query="substring-before(substring-after(//processing-instruction('define')[starts-with(., 'ProductVersionMajor =')],'"'),'"') ">
也没有成功。错误是
错误MSB4018:“XmlPeek”任务意外失败。\ r 错误MSB4018:System.Xml.XPath.XPathException:表达式必须求值为节点集。\ r \ n 错误MSB4018:在System.Xml.XPath.XPathNavigator.Select(XPathExpression expr)\ r \ n 错误MSB4018:在Microsoft.Build.Tasks.XmlPeek.Execute()\ r \ n 错误MSB4018:在Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()\ r \ n 错误MSB4018:在Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost,Task LoggingContext taskLoggingContext,TaskHost taskHost,ItemBucket bucket,TaskExecutionMode howToExecuteTask,Boolean&amp; taskResult)
答案 0 :(得分:1)
从xpath的角度构建以下内容:
Query='substring-before(
substring-after(
//processing-instruction("define")[starts-with(., "ProductVersionMajor =")]
,
'"'
)
,
'"'
)'
答案 1 :(得分:0)
我用这种方法解决了这个问题。希望它有所帮助:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="GetWixDefine"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<File ParameterType="System.String" Required="true" Output="false" />
<DefineName ParameterType="System.String" Required="true" Output="false" />
<Value ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Xml" />
<Using Namespace="System" />
<Using Namespace="System.Text.RegularExpressions" />
<Using Namespace="System.Xml" />
<Code Type="Fragment" Language="cs">
<![CDATA[
this.Value = string.Empty;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(this.File);
string selector = string.Format("//processing-instruction('define')[starts-with(., '{0}')]", this.DefineName);
XmlNode defineNode = xmlDoc.SelectSingleNode(selector);
if (defineNode == null)
throw new Exception("define not found");
string regex = string.Format("{0}[ ]*=[ ]*\"(?<value>.*)\"", DefineName);
Match match = Regex.Match(defineNode.InnerText, regex);
if (!match.Success)
throw new Exception("cannot match correctly");
this.Value = match.Groups["value"].Value;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild">
<GetWixDefine File="VersionFile.wxi" DefineName="ProductVersion">
<Output TaskParameter="Value" ItemName="ProductVersionValue"/>
</GetWixDefine>
<Message Importance="High" Text="ProductVersion: @(ProductVersionValue)"/>
</Target>
</Project>