59

是否可以在 MSBuild 之外使用 Microsoft 的 XML 文档转换来准备 web.configs?我想使用 PowerShell 进行这些转换,而无需通过 MSBuild 引擎运行。如果 Microsoft 使用标准 XSLT,在 PowerShell 中将很容易做到。据我所知,我必须使用他们的 C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll 这需要构建引擎。谢谢

4

8 回答 8

108

我创建了一个小函数来在 PowerShell 中处理 Microsoft 的 XML 文档转换。

我将 Microsoft.Web.XmlTransform.dll 文件从 Visual Studio 构建文件夹复制到我的脚本路径,但如果您愿意,可以从源文件夹中引用它。

function XmlDocTransform($xml, $xdt)
{
    if (!$xml -or !(Test-Path -path $xml -PathType Leaf)) {
        throw "File not found. $xml";
    }
    if (!$xdt -or !(Test-Path -path $xdt -PathType Leaf)) {
        throw "File not found. $xdt";
    }

    $scriptPath = (Get-Variable MyInvocation -Scope 1).Value.InvocationName | split-path -parent
    Add-Type -LiteralPath "$scriptPath\Microsoft.Web.XmlTransform.dll"

    $xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
    $xmldoc.PreserveWhitespace = $true
    $xmldoc.Load($xml);

    $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdt);
    if ($transf.Apply($xmldoc) -eq $false)
    {
        throw "Transformation failed."
    }
    $xmldoc.Save($xml);
}

使用 web.release.config 转换 web.config:

XmlDocTransform -xml "Web.config" -xdt "Web.Release.config"

或者,您可以使用 Sayed 的自引导 Xml 转换脚本,该脚本将为您获取 Microsoft.Xml.Xdt.dll:

https://gist.github.com/sayedihashimi/f1fdc4bfba74d398ec5b

于 2013-05-28T18:00:33.560 回答
14

转换的逻辑包含在 TransformXml 任务本身中。如果您想从代码中调用它,则必须使用带有模拟引擎的 MSBuild API 并执行它。如果你愿意,我有一些代码。

在您的情况下,既然您提到了 PowerShell,那么您最好的办法就是创建一个包装器 MSBuild 文件来调用 TransformXml 任务。我这样说是因为 PowerShell 配置为在 .NET 2.0 下运行,但 TransformXml 任务需要 .NET 4.0。为了从一个虚拟的 MSBuild 文件中调用它,您可以在http://sedodream.com/2010/04/26/ConfigTransformationsOutsideOfWebAppBuilds.aspx查看我的博客,但我还在下面的链接中粘贴了一个示例。

<Project ToolsVersion="4.0" DefaultTargets="Demo" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask TaskName="TransformXml"
             AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>

    <Target Name="Demo">
        <TransformXml Source="app.config"
                      Transform="Transform.xml"
                      Destination="app.prod.config"/>
    </Target>
</Project>

对于mono,这应该可以工作(在 mono 6.4,macos,2019 上测试):

<Project DefaultTargets="TransformConfig" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="TransformXml"
    AssemblyFile="$(MSBuildSDKsPath)/Microsoft.NET.Sdk.Publish/tools/net46/Microsoft.NET.Sdk.Publish.Tasks.dll"/>
  <PropertyGroup>
    <TransformSource>Web.config</TransformSource>
    <Transformer>Web.Live.config</Transformer>
    <Destination>Output.Web.config</Destination>
  </PropertyGroup>
  <Target Name="TransformConfig">
    <Message Text="From TransformSource : $(TransformSource)" />
    <Message Text="Using Transform : $(Transformer)" />
    <Message Text="Output : $(Destination)" />
    <Message Text="MSBuildSDKsPath=$(MSBuildSDKsPath)" Condition="'$(MSBuildSDKsPath)' != ''" />
    <TransformXml Source="$(TransformSource)" Transform="$(Transformer)" Destination="$(Destination)"/>
  </Target>
</Project>

您可以使用它运行msbuild或提供参数

msbuild /p:TransformSource=... /p:Transformer=...
于 2012-01-24T17:08:38.480 回答
11

根据 Michel 的回答,我编写了一个 C# 函数来完成相同的任务。

当然,您可以使用 PowerShell 调用生成的 DLL,但我实际上是在寻找一个完全程序化的版本,所以在这里,以防其他人正在寻找类似的解决方案:

using Microsoft.Web.XmlTransform;

...

public static void TransformConfig(string configFileName, string transformFileName)
{
     var document = new XmlTransformableDocument();
     document.PreserveWhitespace = true;
     document.Load(configFileName);

     var transformation = new XmlTransformation(transformFileName);
     if (!transformation.Apply(document))
     {
         throw new Exception("Transformation Failed");
     }
     document.Save(configFileName);
}

您只需要包含对以下内容的引用:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.XmlTransform.dll

于 2014-02-02T23:18:15.117 回答
10

Microsoft 已将 XDT 发布到 codeplex http://xdt.codeplex.com和作为 NuGet 包https://www.nuget.org/packages/Microsoft.Web.Xdt/。我还创建了一个带有 MSBuild 任务、TransformXml 和 .exe 的 NuGet 猪来调用它们https://www.nuget.org/packages/SlowCheetah.Xdt/1.1.6-beta

对于 PowerShell,我创建了一个自引导脚本,您可以使用它https://gist.github.com/sayedihashimi/f1fdc4bfba74d398ec5b

有关自引导脚本的更多信息,请访问http://sedodream.com/2014/07/22/StopCheckinginBinariesInsteadCreateSelfbootstrappingScripts.aspx

于 2014-07-25T08:17:44.357 回答
7

我稍微更新了脚本以使其与最新版本的 powershell 一起工作并使其更容易一些。

function XmlDocTransform($xml, $xdt)
{
      $scriptpath = $PSScriptRoot + "\"
      $xmlpath = $scriptpath + $xml
      $xdtpath = $scriptpath + $xdt

      if (!($xmlpath) -or !(Test-Path -path ($xmlpath) -PathType Leaf)) {
         throw "Base file not found. $xmlpath";
      }

      if (!($xdtpath) -or !(Test-Path -path ($xdtpath) -PathType Leaf)) {
         throw "Transform file not found. $xdtpath";
      }

      Add-Type -LiteralPath "$PSScriptRoot\Microsoft.Web.XmlTransform.dll"

      $xmldoc = New-Object   Microsoft.Web.XmlTransform.XmlTransformableDocument;
      $xmldoc.PreserveWhitespace = $true
      $xmldoc.Load($xmlpath);

      $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdtpath);
      if ($transf.Apply($xmldoc) -eq $false)
      {
          throw "Transformation failed."
      }
      $xmldoc.Save($xmlpath);

      Write-Host "Transformation succeeded" -ForegroundColor Green
  }

并调用函数使用

 XmlDocTransform "App.config" "App.acc.config"
于 2016-10-11T06:40:20.873 回答
5

看看使用 MSDeploy,因为它具有 PowerShell 脚本 API,允许您转换和部署您的包。

您还可以查看XML-Document-Transform,如果您愿意,您可以编写自己的代码来执行转换。

这是一个执行类似操作的 codeplex 项目。XDT 转换工具

于 2012-01-24T17:15:42.707 回答
0

所以稍微扩展以递归工作

    function XmlDocTransform($xml, $xdt)
    {
        if (!$xml -or !(Test-Path -path $xml -PathType Leaf)) {
            throw "File not found. $xml";
        }
        if (!$xdt -or !(Test-Path -path $xdt -PathType Leaf)) {
            throw "File not found. $xdt";
        }
        $scriptPath = (Get-Variable MyInvocation -Scope 1).Value.InvocationName | split-path -parent
        Add-Type -LiteralPath "$scriptPath\Microsoft.Web.XmlTransform.dll"
        $xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
        $xmldoc.PreserveWhitespace = $true
        $xmldoc.Load($xml);
        $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdt);
        if ($transf.Apply($xmldoc) -eq $false)
        {
            throw "Transformation failed."
        }
        $xmldoc.Save($xml);
    }
    function DoConfigTransform($webFolder, $environment)
    {
        $allConfigFiles = Get-ChildItem $webFolder -File -Filter *.config -Recurse
          $transformFiles = $allConfigFiles | Where-Object {$_.Name -like ("*." + $environment + ".config")} | %{$_.fullname}
          ForEach($item in $transformFiles)
          {
            $origFile = $item -replace("$environment.",'')
              XmlDocTransform -xml $origFile -xdt $origFile$item
              #Write-Output ("orig = " + $origFile + ", transform = " + $item)
          }
          cd C:\WebApplications\xxx\xxx\xxx\
          .\PostDeploy.ps1
    }
    DoConfigTransform -webFolder "C:\WebApplications\xxx\xxx\xxx" -environment "xx-xxx-xx"

所以 DoConfigTransform 逻辑如下:

  • 递归查找所有配置文件
  • 查找我们所在环境的所有转换模板 #passed in 作为参数
  • 对于每个转换文件,找到相应的配置
  • 然后做变换
  • 代码运行部署后脚本以删除所有不需要的转换文件。
于 2019-03-07T15:18:14.563 回答
0

我在原始发布之后很长时间才来到这篇文章,但它帮助解决了我的问题,所以我想我会把我的解决方案(基于上面的解决方案)放在这里,供任何与当前的 Visual Studio / msbuild 安装有相同问题的人使用。

目前在 VS 构建时转换是使用 SlowCheetah nuget pkg 完成的。如果你可以在你的项目中依赖这个包,你可以使用我在下面放置的脚本,它会根据安装的 cheetah 版本自动找到所需的程序集,并根据需要执行你的转换。

希望这可以帮助某人。

param(  
  [ValidateScript({$(Test-Path $_) -eq $true})]
  [string] $NuGetRootPath,

  [ValidateScript({$(Test-Path $_) -eq $true})]
  [string] $BaseFile,

  [ValidateScript({$(Test-Path $_) -eq $true})]
  [string] $TransformFile,

  [string] $TargetPath
)

"[INFO] Creating Custom XML Transform..." | Out-Default   
"[INFO] ==> Source:    $BaseFile" | Out-Default   
"[INFO] ==> Transform: $TransformFile" | Out-Default   
"[INFO] ==> Target:    $TargetPath" | Out-Default   

$cheetahDir = Join-Path $NuGetRootPath *SlowCheetah* | Resolve-Path | Select-Object -Last 1 -ExpandProperty Path
$xformDll = Join-Path $cheetahDir "tools\Microsoft.Web.XmlTransform.dll" | Resolve-Path | Select-Object -ExpandProperty Path
Add-Type -LiteralPath $xformDll

$xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
$xmldoc.PreserveWhitespace = $true
$xmldoc.Load($BaseFile);

"[INFO] Running Transform..." | Out-Default
$transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($TransformFile);
if ($transf.Apply($xmldoc) -eq $false) {
    throw "[ERROR] Transformation failed."
}

$xmldoc.Save($TargetPath);
"[INFO] Transformation Complete..." | Out-Default
于 2020-04-28T15:53:41.600 回答