1. 程式人生 > 其它 >如何規範化更新程式的config配置檔案

如何規範化更新程式的config配置檔案

一.背景

​ 一般如果通過包管理平臺管理客戶環境的應用和服務,在升級場景下一般是增量更新,不會更新應用的配置檔案,如果人工更改客戶環境的配置檔案,成本較大。本文介紹瞭如何通過平臺更新應用的配置檔案方法。

二.原理

三.步驟

1、建立更新檔案

​ 在更新包中建立一個資料夾config_migration,資料夾中放字尾為_update.config的檔案。xxxx_update.config,xxxx代表應用名稱。

​ 在推包時程式會自動檢測是否存在該檔案,有則進行執行。

2、如何定義更新檔案

  • xxxx_update.config檔案內容遵循了微軟標準的 xdt:Transform 語法。
  • XML-Document-Transform 名稱空間定義兩個特性:Locator 和 Transform。
  • Locator 特性指定要以某種方式更改的 Web.config 元素或一組元素。
  • Transform 特性指定要對 Locator 特性所查詢的元素執行哪些操作。

3、特性語法

Locator特性語法

  • Condition:指定XPath表示式,該表示式會追加到當前元素的 XPath 表示式。 選擇了與組合 XPath 表示式匹配的元素。
  • Match:選擇針對指定的一個或多個特性具有匹配值的一個或多個元素。 如果指定了多個特性名稱,則將僅選擇與所有指定特性匹配的元素。
  • XPath:
    指定應用於開發Web.config檔案的絕對XPath表示式。與Condition不同,所指定的表示式不追加到與當前元素對應的隱式XPath表示式

Transform特性語法

  • Replace :將所選的元素替換為在轉換檔案中指定的元素。
  • Insert:將轉換檔案中定義的元素作為所選的一個或多個元素的同級進行新增。 該新元素被新增到任何集合的末尾。
  • InsertBefore:將轉換 XML 中定義的元素直接插入到由指定 XPath 表示式選擇的元素之前。 該 XPath 表示式必須是一個絕對錶達式,因為它作為一個整體應用於開發 Web.config 檔案,而不只是追加到當前元素的隱式 XPath 表示式中。
  • InsertAfter:將轉換 XML 中定義的元素直接插入到由指定 XPath 表示式選擇的元素之後。 該 XPath 表示式必須是一個絕對錶達式。
  • Remove:移除選定元素。 如果選擇了多個元素,則移除第一個元素。
  • RemoveAll:移除選定的一個或多個元素。
  • RemoveAttributes:從選擇元素中移除指定特性。
  • SetAttributes:僅設定指定元素的指定屬性

4、語法示例:

Locator 特性語法示例

Condition:指定XPath表示式,該表示式會追加到當前元素的 XPath 表示式。 選擇了與組合 XPath 表示式匹配的元素。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 更新 connectionStrings 下name 等於 oldname 或著 providerName 等於 oldprovider 的元素內容(連name都更新)-->
  <connectionStrings>
    <add name="newconnect" connectionString="newstring" providerName="newprovider" xdt:Transform="Replace" xdt:Locator="Condition(@name='oldname'or @providerName='oldprovider')" />
  </connectionStrings>
</configuration>

Match:選擇針對指定的一個或多個特性具有匹配值的一個或多個元素。 如果指定了多個特性名稱,則將僅選擇與所有指定特性匹配的元素。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 更新 connectionStrings 下name 等於 "oldconnect" 元素的內容(不更新name的值)-->
  <connectionStrings>
    <add name="oldconnect" connectionString="newstring" providerName="newprovider" xdt:Transform="Replace" xdt:Locator="Match(name)" />
  </connectionStrings>
</configuration>

XPath:指定應用於開發Web.config檔案的絕對XPath表示式。與Condition不同,所指定的表示式不追加到與當前元素對應的隱式XPath表示式

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 更新 connectionStrings 下name 等於 "test" 或 providerName 等於"System.Data.SqlClient" 元素的內容(更新name的值)-->
  <connectionStrings>
    <add name="test" connectionString="newstring" providerName="newprovider" 
       xdt:Transform="Replace" 
       xdt:Locator="XPath(configuration/connectionStrings[@name='test'
         or @providerName='System.Data.SqlClient'])" />
  </connectionStrings>
</configuration>test

Transform 特性語法示例

Replace :將所選的元素替換為在轉換檔案中指定的元素。

Insert:將轉換檔案中定義的元素作為所選的一個或多個元素的同級進行新增。 該新元素被新增到任何集合的末尾。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 在appsetting中插入一個鍵值 -->
  <appSettings>
    <add key="test" value="11"  xdt:Transform="Insert" />
  </appSettings>
  </configuration>

InsertBefore:將轉換 XML 中定義的元素直接插入到由指定 XPath 表示式選擇的元素之前。 該 XPath 表示式必須是一個絕對錶達式,因為它作為一個整體應用於開發 Web.config 檔案,而不只是追加到當前元素的隱式 XPath 表示式中。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例  在authorization下的deny元素之前插入一個allow元素-->
  <authorization>
    <allow roles="Admins"
      xdt:Transform="InsertBefore(/configuration/system.web/authorization/deny[@users='*'])" />
  </authorization>
</configuration>

InsertAfter:將轉換 XML 中定義的元素直接插入到由指定 XPath 表示式選擇的元素之後。 該 XPath 表示式必須是一個絕對錶達式。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例  在authorization下的allow元素之後插入一個deny 元素-->
  <authorization>
    <deny users="UserName"
      xdt:Transform="InsertAfter
        (/configuration/system.web/authorization/allow[@roles='Admins'])" />
  </authorization>
</configuration>

Remove:移除選定元素。 如果選擇了多個元素,則移除第一個元素。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 刪除 name等於 test的add元素-->
  <connectionStrings>
    <add xdt:Transform="Remove" xdt:Locator="Condition(@name='test')"/>
  </connectionStrings>
</configuration>

RemoveAll:移除選定的一個或多個元素。

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 刪除connectionStrings 元素下所有add元素-->
  <connectionStrings>
    <add xdt:Transform="RemoveAll" />
  </connectionStrings>
</configuration>

RemoveAttributes:從選擇元素中移除指定特性

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 移除connectionStrings 元素下name等於'oldname'的providerName屬性 -->
  <connectionStrings>
    <add name="connect01" connectionString="newstring" providerName="newprovider" xdt:Transform="RemoveAttributes(providerName)" xdt:Locator="Condition(@name='oldname')" />
  </connectionStrings>
</configuration>

SetAttributes:僅設定指定元素的指定屬性

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--示例 將web應用的框架版本 更換成4.8-->
 <system.web>
  <compilation  targetFramework="4.8"  xdt:Transform="SetAttributes(targetFramework)" />
   </system.web>
</configuration>

父元素上的 Transform 特性會影響子元素,即使沒有為子元素指定任何 Transform 也是如此。例如,如果將特性 xdt:Transform="Replace" 放在 system.web 元素中,則 system.web 元素的所有子元素將替換為轉換檔案中的內容。

參考:用於使用 Visual Studio 部署 Web 應用程式專案的 Web.config 轉換語法

5、呼叫方法

  1. 引用 Microsoft.Web.XmlTransform
  2. 參考程式碼
        /// <summary>
        /// 執行xml轉換
        /// </summary>
        /// <param name="sourceFile">源配置檔案</param>
        /// <param name="transformFile">轉換配置檔案</param>
        /// <param name="distinctFile">目標配置檔案</param>
        /// <param name="logger">日誌引數</param>
        public static void Execute(string sourceFile, string transformFile, string distinctFile, IXmlTransformationLogger logger)
        {
            if (!System.IO.File.Exists(sourceFile) && !System.IO.File.Exists(transformFile))
            {
                throw new FileNotFoundException("The config or transform file do not exist!");
            }

            using (var doc = new Microsoft.Web.XmlTransform.XmlTransformableDocument())
            {
                doc.Load(sourceFile);
                using (var tranform = new Microsoft.Web.XmlTransform.XmlTransformation(transformFile, logger))
                {
                    if (tranform.Apply(doc))
                    {
                        doc.Save(distinctFile);
                    }
                    else
                    {
                        throw new InvalidOperationException("XML轉換失敗,詳情參見日誌。");
                    }
                }
            }
        }