【问题标题】:XPath expression for parsing WiX Processing-Instructions as MsBuild properties用于将 WiX 处理指令解析为 MsBuild 属性的 XPath 表达式
【发布时间】:2023-04-04 23:10:01
【问题描述】:

我有以下 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=")],"),")' 有一个无效的标记。 p>

假设 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)

【问题讨论】:

    标签: xpath msbuild wix


    【解决方案1】:

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

    Query='substring-before(
        substring-after(
             //processing-instruction("define")[starts-with(., "ProductVersionMajor =")]
             ,
             &apos;&quot;&apos;
             )
             ,
        &apos;&quot;&apos;
        )' 
    

    【讨论】:

      【解决方案2】:

      我用这种方法解决了这个问题。希望对您有所帮助:

      <?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>
      

      【讨论】:

        猜你喜欢
        • 2023-03-16
        • 1970-01-01
        • 2010-10-05
        • 1970-01-01
        • 1970-01-01
        • 2022-11-29
        • 1970-01-01
        • 2010-11-24
        • 2015-06-01
        相关资源
        最近更新 更多