web-config - XDT 转换 : InsertBefore - Locator Condition is ignored

标签 web-config web-config-transform xdt-transform

我有一个 web.config 文件,我需要在其中插入 <configSections />元素或操作该节点的子节点(如果它已经存在)。
如果它已经存在,我不想再次插入它(显然,因为它只允许存在一次)。

通常,这不会有问题,但是:

If this element is in a configuration file, it must be the first child element of the element.



Source: MSDN .

所以如果我使用 xdt:Transform="InsertIfMissing" <configSections />元素将始终插入在任何现有子元素之后(并且总是有一些),违反了上述限制它必须是 <configuration /> 的第一个子元素

我试图通过以下方式完成这项工作:

 <configSections
    xdt:Transform="InsertBefore(/configuration/*[1])"
    xdt:Locator="Condition(not(.))" />

如果<configSections />,哪个工作完美元素不存在。但是,我指定的条件似乎被忽略了。

事实上,我已经尝试了一些条件,例如:
Condition(not(/configuration[configSections]))
Condition(/configuration[configSections] = false())
Condition(not(/configuration/configSections))
Condition(/configuration/configSections = false())

最后,出于绝望,我尝试了:
Condition(true() = false()) 

它仍然插入了<configSections />元素。

请务必注意,我正在尝试将其包含在 NuGet 包中,因此我将无法使用自定义转换 ( like the one AppHarbor uses )。

有没有其他聪明的方法可以让我的元素仅在它不存在的时候放在正确的位置?

要对此进行测试,请使用 AppHarbors config transform tester .将 Web.config 替换为以下内容:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="initialSection" />
  </configSections>
</configuration>

和 Web.Debug.config 具有以下内容:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

  <configSections
    xdt:Transform="InsertBefore(/configuration/*[1])"
    xdt:Locator="Condition(true() = false())" />

  <configSections>
    <section name="mySection" xdt:Transform="Insert" />
  </configSections>

</configuration>

结果会显示两个 <configSections />元素,第一个包含“mySection”的元素,如 InsertBefore Transform 中指定的那样。
为什么没有考虑定位条件?

最佳答案

所以在遇到同样的问题后,我想出了一个解决方案。它不漂亮也不优雅,但它有效。 (至少在我的机器上)

我只是将逻辑拆分为 3 个不同的语句。首先,我在正确的位置(第一个)添加一个空的 configSections。然后我将新配置插入 最后 configSections,如果它是唯一的,则为新的,否则为先前存在的。
最后,我删除了任何可能存在的空 configSections 元素。我无缘无故地使用 RemoveAll,您可能应该使用 Remove。

整体代码如下所示:

<configSections xdt:Transform="InsertBefore(/configuration/*[1])" />
<configSections xdt:Locator="XPath(/configuration/configSections[last()])">
    <section name="initialSection" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</configSections>
<configSections xdt:Transform="RemoveAll" xdt:Locator="Condition(count(*)=0)" />

仍然没有回答的问题是为什么 InsertBefore 没有考虑定位器条件。或者为什么我不能处理 InsertBefore 的空匹配集,因为这会让我做一些有趣的事情,比如
//configuration/*[position()=1 and not(local-name()='configSections')]

老实说,这是做我想要实现的目标的更清晰的方法。

关于web-config - XDT 转换 : InsertBefore - Locator Condition is ignored,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18737022/

相关文章:

asp.net - 多个 web.config 重定向规则

node.js - Windows Azure 网站覆盖了我的 node.js 应用程序中的 404 和 500 错误页面

c# - web.config 文件在 C# 中如何工作?

.net - 根据 Web.config 转换中的子节点值选择节点

visual-studio-2010 - 如何在调试时查看转换后的 web.config (SlowCheetah)

NuGet 包转换配置转换文件

xpath - 匹配子节点内容的 xdt 变换定位器

iis-7 - 我可以以编程方式定义我的 IIS7 站点绑定(bind)(例如 foo.domain.com)吗?

asp.net - 发布不是在转换 web.config?

xml - 当目标配置文件的结构未知时如何处理深度 XDT 转换?