2

我有以下 wix 包括VersionFile.wxi

<?xml version="1.0" encoding="utf-8"?>
<Include>
  <?define ProductVersionMajor = "1" ?>
  <?define ProductVersionMinor = "00" ?>

  <?define ProductName= "MyProduct" ?>

  <?define UpgradeCode = "myUpgradeCode" ?>
</Include>

现在,我想使用 XmlPeek 和 XPath 查询将 ProductVersionMajor 设为“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(., &quot;ProductVersionMajor =&quot;)]">
      <Output TaskParameter="Result" ItemName="Peeked" />
    </XmlPeek>

    <XmlPeek XmlInputPath="VersionFile.wxi"
             Query="//processing-instruction('define')[starts-with(., &quot;ProductVersionMajor=&quot;)]">
      <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(&quot;define&quot;)[starts-with(., &quot;ProductVersionMajor=&quot;)],&quot;),&quot;)">
  <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 =')],&apos;&quot;&apos;),&apos;&quot;&apos;) ">

也没有成功。错误是

错误 MSB4018: "XmlPeek" 任务意外失败。\r 错误 MSB4018: System.Xml.XPath.XPathException: 表达式必须计算为节点集。\r 错误 MSB4018: 在 System.Xml.XPath.XPathNavigator.Select(XPathExpression expr)\r 错误 MSB4018:在 Microsoft.Build.Tasks.XmlPeek.Execute()\r 错误 MSB4018:在 Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()\r 错误 MSB4018:在Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, Task LoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask, Boolean& taskResult)

4

2 回答 2

1

从 xpath 的角度来看,应该做以下事情:

Query='substring-before(
    substring-after(
         //processing-instruction("define")[starts-with(., "ProductVersionMajor =")]
         ,
         &apos;&quot;&apos;
         )
         ,
    &apos;&quot;&apos;
    )' 
于 2013-04-26T14:32:07.510 回答
1

我用这种方法解决了这个问题。希望能帮助到你:

<?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>
于 2014-10-31T08:14:56.690 回答