使用XSLT重新定位Visual Studio解决方案文件

时间:2018-07-20 08:33:04

标签: xml xslt visual-studio-2017

我目前正在与MSBuild作战,该软件无法在Github上的库中构建解决方案文件。问题似乎是由于某些莫名其妙的原因,Microsoft决定需要在XML文件中设置目标SDK,并且指定的版本当然与VM中安装的版本不匹配。

所以我想要一个简单的方法来更新它。我决定使用xsltproc来执行此操作。我创建了以下XSLT文件:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="WindowsTargetPlatformVersion"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="WindowsTargetPlatformVersion/text()[.='X']">
        <xsl:value-of select="$WindowsTargetPlatformVersion"/>
    </xsl:template>
</xsl:stylesheet>

但是由于某种原因,这不适用于解决方案文件。我要修改的解决方案文件的示例如下:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{1A234565-926D-49B2-83E4-D56E0C38C9F2}</ProjectGuid>
    <RootNamespace>libconfig</RootNamespace>
    <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <PlatformToolset>v141</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <PlatformToolset>v141</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>15.0.26919.1</_ProjectFileVersion>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
    <IntDir>$(ProjectName).$(Configuration)\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <OutDir>$(SolutionDir)$(Configuration)\</OutDir>
    <IntDir>$(ProjectName).$(Configuration)\</IntDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PreprocessorDefinitions>LIBCONFIG_EXPORTS;YY_NO_UNISTD_H;YY_USE_CONST;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <CompileAs>CompileAsC</CompileAs>
    </ClCompile>
    <Link>
      <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <OutputFile>$(OutDir)$(ProjectName)_d.dll</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <MapExports>true</MapExports>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention />
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <PreprocessorDefinitions>LIBCONFIG_EXPORTS;YY_NO_UNISTD_H;YY_USE_CONST;_CRT_SECURE_NO_DEPRECATE;_STDLIB_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <CompileAs>CompileAsC</CompileAs>
    </ClCompile>
    <Link>
      <AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention />
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="grammar.c" />
    <ClCompile Include="libconfig.c" />
    <ClCompile Include="scanctx.c" />
    <ClCompile Include="scanner.c" />
    <ClCompile Include="strbuf.c" />
    <ClCompile Include="strvec.c" />
    <ClCompile Include="util.c" />
    <ClCompile Include="wincompat.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\ac_config.h" />
    <ClInclude Include="grammar.h" />
    <ClInclude Include="libconfig.h" />
    <ClInclude Include="parsectx.h" />
    <ClInclude Include="private.h" />
    <ClInclude Include="scanctx.h" />
    <ClInclude Include="scanner.h" />
    <ClInclude Include="strbuf.h" />
    <ClInclude Include="strvec.h" />
    <ClInclude Include="util.h" />
    <ClInclude Include="win32\stdint.h" />
    <ClInclude Include="wincompat.h" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

我不知道为什么xsltproc拒绝替换文本。我从bash像这样运行它:

xsltproc --stringparam WindowsTargetPlatformVersion $SDKVERSION retarget.xslt $SOLUTIONFILE

如果我使用标签创建一个简单的xml文件,它将按预期工作。解决方案文件不起作用。

1 个答案:

答案 0 :(得分:1)

Visual Studio解决方案文件具有默认名称空间(此处为xlmns ...)

 <Project DefaultTargets="Build" ToolsVersion="15.0" 
          xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

但是您尚未在XSLT中对此进行说明。如果您的模板匹配“ WindowsTargetPlatformVersion”,则它试图匹配没有命名空间中的元素

您只需要在XSLT中声明名称空间并绑定到前缀,然后在模板匹配项中使用该名称空间即可。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ms="http://schemas.microsoft.com/developer/msbuild/2003">
    <xsl:param name="WindowsTargetPlatformVersion"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ms:WindowsTargetPlatformVersion/text()[.='X']">
        <xsl:value-of select="$WindowsTargetPlatformVersion"/>
    </xsl:template>
</xsl:stylesheet>

如果您可以使用XSLT 2.0(我猜不是,如果您在Microsoft的世界中),则可以使用xpath-default-namespace,因此不需要绑定到前缀

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xpath-default-namespace="http://schemas.microsoft.com/developer/msbuild/2003">
    <xsl:param name="WindowsTargetPlatformVersion"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="WindowsTargetPlatformVersion/text()[.='X']">
        <xsl:value-of select="$WindowsTargetPlatformVersion"/>
    </xsl:template>
</xsl:stylesheet>