是否可以使用Microsoft的XML文档转换,在MSBuild之外准备web.configs?我想使用PowerShell进行这些转换,而无需通过MSBuild引擎运行它。如果Microsoft使用标准XSLT,那么在PowerShell中很容易做到。据我所知,我必须使用他们需要构建引擎的C:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft.Web.Publishing.Tasks.dll。谢谢
我创建了一个小函数来处理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:
转换的逻辑包含在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>
微软已将XDT发布到codeplex http://xdt.codeplex.com和作为NuGet包https://www.nuget.org/packages/Microsoft.Web.Xdt/。我还创建了一个带有MSBuild任务的NuGet pig,TransformXml和一个.exe来调用它们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的自引导脚本的更多信息。
根据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
我稍微更新了脚本以使其与最新版本的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"
看一下使用MSDeploy,因为它有PowerShell脚本API,允许您转换和部署您的包。
您还可以查看XML-Document-Transform,如果您愿意,可以编写自己的代码来执行Transform。
这是一个类似的项目,做了类似的事情.XDT Transformation Tool
因此递归地略微扩展到工作
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逻辑变为: