首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XDT变换:忽略InsertBefore -定位器条件

XDT变换:忽略InsertBefore -定位器条件
EN

Stack Overflow用户
提问于 2013-09-11 09:10:16
回答 1查看 11.7K关注 0票数 26

我有一个web.config文件,如果该节点已经存在,则需要在其中插入<configSections />元素或操作该节点的子节点。

如果它已经存在,我不想再次插入它(显然,它只允许存在一次)。

然而,通常情况下,这不会是一个问题:

如果此元素位于配置文件中,则必须是该元素的第一个子元素。

Source: MSDN

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

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

代码语言:javascript
复制
 <configSections
    xdt:Transform="InsertBefore(/configuration/*[1])"
    xdt:Locator="Condition(not(.))" />

如果<configSections />元素还不存在的话,它可以很好地工作。但是,我指定的条件似乎被忽略了。

事实上,我尝试过一些条件,比如:

代码语言:javascript
复制
Condition(not(/configuration[configSections]))
Condition(/configuration[configSections] = false())
Condition(not(/configuration/configSections))
Condition(/configuration/configSections = false())

最后,出于绝望,我试着:

代码语言:javascript
复制
Condition(true() = false()) 

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

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

只有在元素还不存在的情况下,才有其他聪明的方法将我的元素放在正确的位置吗?

要测试这一点,请使用AppHarbors config transform tester。将Web.config替换为以下内容:

代码语言:javascript
复制
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="initialSection" />
  </configSections>
</configuration>

以及Web.Debug.config中的以下内容:

代码语言:javascript
复制
<?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转换中指定的。为什么没有考虑到定位器的情况?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-27 01:53:24

所以在面对同样的问题后,我想出了一个解决方案。它既不漂亮也不优雅,但很实用。(至少在我的机器上)

我只是把逻辑分成3种不同的陈述。首先,我在正确的位置添加一个空的configSections (第一个)。然后,我将新配置插入到最后一个 configSections,如果它是唯一的配置,它将是新配置,否则将是以前存在的配置。最后,删除所有可能存在的空configSections元素。我使用RemoveAll没有很好的理由,您可能应该使用Remove。

整个代码如下所示:

代码语言:javascript
复制
<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的空匹配集,因为这将允许我做一些有趣的事情,比如

代码语言:javascript
复制
//configuration/*[position()=1 and not(local-name()='configSections')]

老实说,这是我想要做的事情的一个更清晰的方法。

票数 45
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18737022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档