这对我来说很难解释,但我会尽力而为。添加评论以澄清/补充我可能遗漏的任何内容。
背景资料:
- 执行 msbuild 的 NANT(构建过程)版本 0.85.2478.0
- CruiseControl.NET
- Windows Server 2008 R2 64 位
- .NET 框架 3.5
我正在尝试更新/修改 Web 应用程序的 web.config 中的一些设置。我们使用 NANT 代码运行通过 CruiseControl.NET 执行的构建过程。我们正在通过 XslCompiledTransform 并使用样式表和设置文件来更新配置文件。
以下是“UpdateConfig.xslt”文件的样子:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<!-- Set the file output mode -->
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<!-- Get the parameters from the calling application -->
<xsl:param name="defaultSettings" select="'C:\BuildServer\Configuration\ConfigFiles\Defaults.xml'" />
<xsl:param name="buildTypeSettings" select="'NoFile'" />
<xsl:param name="environmentSettings" select="'NoFile'" />
<xsl:param name="projectSettings" select="'NoFile'" />
<xsl:param name="mode" select="''"/>
<!-- Load the various ConfigFileSettings XML files. -->
<xsl:include href="GetSettings.xslt" />
<xsl:variable name="fileset">
<xsl:if test="$defaultSettings != 'NoFile'">
<xsl:element name="File"><xsl:value-of select="$defaultSettings" /></xsl:element>
</xsl:if>
<xsl:if test="$buildTypeSettings != 'NoFile'">
<xsl:element name="File"><xsl:value-of select="$buildTypeSettings" /></xsl:element>
</xsl:if>
<xsl:if test="$environmentSettings != 'NoFile'">
<xsl:element name="File"><xsl:value-of select="$environmentSettings" /></xsl:element>
</xsl:if>
<xsl:if test="$projectSettings != 'NoFile'">
<xsl:element name="File"><xsl:value-of select="$projectSettings" /></xsl:element>
</xsl:if>
</xsl:variable>
<xsl:variable name="Settings">
<xsl:call-template name="loadSettings">
<xsl:with-param name="fileset" select="$fileset" />
</xsl:call-template>
</xsl:variable>
<!-- Define the root node template to distinguish output types. -->
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$mode = 'display'">
<xsl:call-template name="display" />
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Define the default copy template. -->
<xsl:template match="*|node()|comment()|processing-instruction()" priority="-100">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<!-- Skip certain comments. -->
<xsl:template match="comment()[contains(., '=tuc0') and contains(., '<publisher')]" />
<xsl:template match="comment()[contains(., 'add key="')]" priority="10">
<xsl:variable name="key" select="substring-before(substring-after(., 'add key="'), '"')" />
<xsl:if test="count(//add[@key=$key]) = 0"><xsl:copy /></xsl:if>
</xsl:template>
<!-- Look up attribute settings in the $Settings block for all attributes. -->
<xsl:template match="@*">
<xsl:choose>
<xsl:when test="name() = '@key'"><xsl:copy /></xsl:when>
<xsl:otherwise>
<!-- First, build a full xpath to this key as it should appear in settings. -->
<xsl:variable name="setting">
<xsl:call-template name="getSetting">
<xsl:with-param name="node" select="." />
</xsl:call-template>
</xsl:variable>
<!-- Next, get the value from the config file if it's there. -->
<xsl:variable name="value">
<xsl:choose>
<xsl:when test="count(msxsl:node-set($Settings)//setting[@xpath=$setting]) = 1">
<xsl:value-of select="msxsl:node-set($Settings)//setting[@xpath=$setting]/@value" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Finally, return the attribute with its new value -->
<xsl:attribute name="{name()}"><xsl:value-of select="$value" /></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Handle SQL Connection Strings -->
<xsl:template match="@*[(contains(translate(., 'ACDEGILNORSTU ', 'acdegilnorstu'), 'initialcatalog=')
or contains(translate(., 'ABDEST ', 'abdest'), 'database='))
and not(contains(translate(., 'PROVIDE ', 'provide'), 'provider='))]"
priority="1">
<!-- Normalize the connection string -->
<xsl:variable name="lcString" select="translate(., 'ABCDEGILNORSTU ', 'abcdegilnorstu')" />
<!-- Get the database from the string -->
<xsl:variable name="dbname">
<xsl:choose>
<xsl:when test="contains($lcString, 'initialcatalog=')">
<xsl:value-of select="substring-before(substring-after($lcString, 'initialcatalog='), ';')" />
</xsl:when>
<xsl:when test="contains($lcString, 'database=')">
<xsl:value-of select="substring-before(substring-after($lcString, 'database='), ';')" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="SqlDB" select="concat('Initial Catalog=', $dbname, ';')" />
<!-- Get SQL Settings from $Settings. -->
<xsl:variable name="SqlAuth">
<xsl:choose>
<xsl:when test="translate(msxsl:node-set($Settings)//SqlAuth, 'TRUE', 'true') = 'true'">
<xsl:text>Trusted_Connection=YES;</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text>Trusted_Connection=NO;</xsl:text></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="SqlServer">
<xsl:choose>
<xsl:when test="count(msxsl:node-set($Settings)//SqlServer) > 0">
<xsl:value-of select="concat('Data Source=', msxsl:node-set($Settings)//SqlServer, ';')" />
</xsl:when>
<xsl:otherwise>.</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="SqlUser">
<xsl:if test="$SqlAuth = 'Trusted_Connection=NO;' and string-length(msxsl:node-set($Settings)//SqlUser) > 0">
<xsl:value-of select="concat('user id=', msxsl:node-set($Settings)//SqlUser, ';')" />
</xsl:if>
</xsl:variable>
<xsl:variable name="SqlPass">
<xsl:if test="$SqlAuth = 'Trusted_Connection=NO;' and string-length(msxsl:node-set($Settings)//SqlPass) > 0">
<xsl:value-of select="concat('password=', msxsl:node-set($Settings)//SqlPass, ';')" />
</xsl:if>
</xsl:variable>
<xsl:variable name="SqlApp">
<xsl:if test="string-length(msxsl:node-set($Settings)//SqlApp) > 0">
<xsl:value-of select="concat('APP=', msxsl:node-set($Settings)//SqlApp, ';')" />
</xsl:if>
</xsl:variable>
<xsl:attribute name="{name()}"><xsl:value-of select="concat($SqlServer,$SqlDB,$SqlAuth,$SqlUser,$SqlPass,$SqlApp)" /></xsl:attribute>
</xsl:template>
<xsl:template name="getSetting">
<xsl:param name="node" />
<xsl:param name="xpath" select="name($node)" />
<xsl:param name="r" select="'1'" />
<xsl:for-each select="$node"> <!-- Sets the node as current context -->
<!-- Handle any special formatting for identifying settings -->
<xsl:variable name="setting">
<xsl:choose>
<xsl:when test="name(..) = 'FTPLocation' and ../@name">
<xsl:value-of select='concat("[@name='", ../@name, "']/@", $xpath)' />
</xsl:when>
<xsl:when test="name() = 'value' and name(..) = 'add' and ../@key">
<xsl:value-of select='concat("[@key='", ../@key, "']/@", $xpath)' />
</xsl:when>
<xsl:when test="not(self::*)">
<xsl:value-of select="concat('/', '@', $xpath)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('/', $xpath)" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="name(..) = ''">
<xsl:value-of select="$setting" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getSetting">
<xsl:with-param name="node" select=".." />
<xsl:with-param name="xpath" select="concat(name(..), $setting)" />
<xsl:with-param name="r" select="$r + 1" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
这是我传递的设置文件的一部分,其中包含一些有效的值,以及一些无效的值:
<setting xpath="/configuration/General/Settings/add[@key='enableAddrValidationService']/@value" value="true" create="false" dynamic="false" />
<setting xpath="/configuration/General/Settings/add[@key='AddrValidationUrl']/@value" value="bogus" create="false" dynamic="false" />
<setting xpath="/configuration/system.serviceModel/client/endpoint[@name='ValidationServiceSoap']/@address" value="bogus" create="false" dynamic="false" />
<setting xpath="/configuration/applicationSettings/ARTS.Properties.Settings/setting[@name='addrValidationUser']/value" value="bogus" create="false" dynamic="false" />
问题:当我开始构建我们的 Web 应用程序时,它并没有更新我想要/指定的所有配置部分。
我已经用 XmlSpy、Notepad++ 和 XmlQuire 验证了所有的 xpath 表达式,所以我知道 100% 它们是正确的。
我唯一认为不正确的是它在样式表(UpdateConfig.xslt)中,但是这个构建过程不是我编写的,我很难阅读它。
如果有人对出了什么问题或如何更好地调试过程有任何想法,我很想听听他们的意见。
哦,不更新的部分是这个 xpath:
<setting xpath="/configuration/system.serviceModel/client/endpoint[@name='ValidationServiceSoap']/@address" value="bogus" create="false" dynamic="false" />