Процесс Xsl-преобразования через NANT не обновляет все запрошенные xpath
Мне будет сложно объяснить, но я сделаю все возможное. Добавьте комментарии для разъяснений / дополнений ко всему, что я могу пропустить.
Справочная информация:
- NANT (процесс сборки) версия 0.85.2478.0, которая выполняет msbuild
- CruiseControl.NET
- Windows Server 2008 R2 64-разрядная
- .NET Framework 3.5
Я пытаюсь обновить / изменить некоторые настройки в нашем 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" />
Проблема: Когда я запускаю сборку для нашего веб-приложения, оно не обновляет все разделы конфигурации, которые я хочу / указать.
Я проверил все выражения xpath с помощью XmlSpy, Notepad++ и XmlQuire, поэтому я на 100% знаю, что они правильные.
Моя единственная мысль о том, что является неправильным, заключается в том, что она находится в таблице стилей (UpdateConfig.xslt), но этот процесс сборки не был написан мной, и мне трудно читать его.
Если у кого-то есть мысли о том, что не так или как лучше отлаживать процесс, я ЛЮБЛЮ их слышать.
О, раздел, который НЕ обновляется, это xpath:
<setting xpath="/configuration/system.serviceModel/client/endpoint[@name='ValidationServiceSoap']/@address" value="bogus" create="false" dynamic="false" />