【问题标题】:update 3rd party's .config transformation's from installer从安装程序更新第 3 方的 .config 转换
【发布时间】:2026-02-13 02:10:01
【问题描述】:

我有 2 个需要配置的 .config 文件。一个是web.config,一个是app.config,这两个文件都来自我们的代码在其中运行的第三方供应商。所以我们需要对其进行调整,以便它能够看到我们的代码。

我的计划是使用 xslt 获取我们的 .config 文件并将其合并到第 3 方文件中。

我已经看到了一些关于如何使用 msbuild 执行此类操作的示例,但由于我们是在现场执行此操作,因此我们将不得不使用安装程序来执行此操作。任何帮助将不胜感激。

示例: 我们开始:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

自定义部分

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="productName" type="company.productName, company, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" />
  </configSections>
  <productName defaultProvider="Provider1">
    <providers>
      <clear />
      <add name="Provider1" type="Company.Product.Authentication.Provider1, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="localhost:5555" />
      <add name="Provider2" type="Company.Product.Authentication.Provider2, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="demo.example.com" />
    </providers>
  </productName>
</configuration>

结尾是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="productName" type="company.productName, company, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" />
  </configSections>
  <productName defaultProvider="Provider1">
    <providers>
      <clear />
      <add name="Provider1" type="Company.Product.Authentication.Provider1, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="localhost:5555" />
      <add name="Provider2" type="Company.Product.Authentication.Provider2, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="demo.example.com" />
    </providers>
  </productName>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

【问题讨论】:

  • 转换是否只是将configuration 的一个孩子复制到另一个?
  • @Alejandro:是的,检查它是否存在,如果不添加它。如果是,那就别管它了。
  • 这不是我写的。你需要弄清楚check if it is thereleave it alone是什么意思。
  • @Alejandro:感谢您的提示,我真的不太使用 XML,但是从 SQL 的角度来看,它会检查元素是否存在,如果存在则更新它以防它发生变化.或者,如果它确实存在,则会发生插入并将新元素添加到正确的位置。

标签: c# .net xslt config transformation


【解决方案1】:

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:apply-templates select="document('test.xml')/*">
            <xsl:with-param name="pContext" select="*"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="*[*]">
        <xsl:param name="pContext" select="/.."/>
        <xsl:variable name="vCurrent" select="."/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:copy-of select="$pContext/@*"/>
            <xsl:for-each select="*">
                <xsl:apply-templates select=".">
                    <xsl:with-param name="pContext"
                         select="$pContext/*[name()=name(current())]"/>
                </xsl:apply-templates>
            </xsl:for-each>
            <xsl:for-each select="$pContext/*">
                <xsl:apply-templates
                     select="(.)[not($vCurrent/*[name()=name(current())])]"/>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[not(*)]">
        <xsl:param name="pContext" select="/.."/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:copy-of select="$pContext/@*"/>
            <xsl:apply-templates
                 select="node()[not($pContext)]|$pContext/node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

有了这个输入:

<configuration>
    <runtime>
        <gcServer enabled="true"/>
    </runtime>
</configuration>

还有这个test.xml

<configuration>
    <configSections>
        <section name="productName" type="company.productName, company, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" />
    </configSections>
    <productName defaultProvider="Provider1">
        <providers>
            <clear />
            <add name="Provider1" type="Company.Product.Authentication.Provider1, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="localhost:5555" />
            <add name="Provider2" type="Company.Product.Authentication.Provider2, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="demo.example.com" />
        </providers>
    </productName>
</configuration>

输出:

<configuration>
    <configSections>
        <section name="productName" type="company.productName, company, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c"></section>
    </configSections>
    <productName defaultProvider="Provider1">
        <providers>
            <clear></clear>
            <add name="Provider1" type="Company.Product.Authentication.Provider1, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="localhost:5555"></add>
            <add name="Provider2" type="Company.Product.Authentication.Provider2, Company.Product, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d9072a6c5128d57c" hostName="demo.example.com"></add>
        </providers>
    </productName>
    <runtime>
        <gcServer enabled="true"></gcServer>
    </runtime>
</configuration>

注意:三个规则。文档根规则:将遍历树更改为需要更新的源,并将输入源保持为$pContext。带有元素子元素的元素规则:使用属性复制自身,使用$pContext 的属性更新属性(这是由处理器完成的,因为creating attributes rules),将模板应用于具有新$pContext 的元素子元素(旧@987654330 的子元素@ 具有相同的名称),将模板应用于 $pContext 的孩子,这些孩子与任何孩子的名字都不匹配。没有元素子元素的元素规则:使用$pContext 属性更新的属性复制自身,如果$pContext 中有节点,则复制它,从而替换元素内容(如果$pContext 中有空元素,甚至剥离)。

【讨论】:

  • 效果很好,如果你能解释一下它是如何工作的,那就太好了!
  • @Matt Heffernan:不客气!我会回来补充解释。
  • @Matt Heffernan:添加了说明。
最近更新 更多