0

这对我来说很难解释,但我会尽力而为。添加评论以澄清/补充我可能遗漏的任何内容。

背景资料:

  • 执行 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(., '&lt;publisher')]" />
      <xsl:template match="comment()[contains(., 'add key=&quot;')]" priority="10">
        <xsl:variable name="key" select="substring-before(substring-after(., 'add key=&quot;'), '&quot;')" />
        <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=&apos;", ../@name, "&apos;]/@", $xpath)' />
          </xsl:when>
          <xsl:when test="name() = 'value' and name(..) = 'add' and ../@key">
            <xsl:value-of select='concat("[@key=&apos;", ../@key, "&apos;]/@", $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" /> 
4

0 回答 0