XDT转换:InsertBefore-定位条件被忽略 [英] XDT Transform: InsertBefore - Locator Condition is ignored

查看:135
本文介绍了XDT转换:InsertBefore-定位条件被忽略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a web.config file in which I need to either insert the <configSections /> element or manipulate children of that node if it already exists.
If it already exists I don't want to insert it again (obviously, as it is only allowed to exist once).

通常,这不会有问题,

如果此元素在配置文件中,则它必须是该元素的第一个子元素.

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

来源:MSDN .

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

So if I use xdt:Transform="InsertIfMissing" the <configSections /> element will always be inserted after any existing child elements (and there are always some), violating the above restriction of it having to be the first child element of <configuration />

我尝试通过以下方式进行这项工作:

I attempted to make this work in the following way:

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

如果<configSections />元素尚不存在,则可以完美地工作.但是,我指定的条件似乎被忽略了.

Which works perfect, if the <configSections /> element doesn't already exist. However, the condition I've specified seems to be ignored.

事实上,我已经尝试了一些条件,例如:

In fact, I've tried a few conditions like:

Condition(not(/configuration[configSections]))
Condition(/configuration[configSections] = false())
Condition(not(/configuration/configSections))
Condition(/configuration/configSections = false())

最后,出于绝望,我尝试了:

Finally, out of desperation, I tried:

Condition(true() = false()) 

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

请注意,我正在尝试将其包含在NuGet软件包中,因此我将无法使用自定义转换(

It is important to note that I'm trying to include this in a NuGet package, so I will be unable to use a custom transform (like the one AppHarbor uses).

是否还有其他聪明的方法可以将元素正确放置在正确的位置?

Is there any other clever way to get my element in the right place only if it doesn't yet exist?

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

To test this out, use AppHarbors config transform tester. Replace the Web.config with the following:

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

和带有以下内容的Web.Debug.config:

And Web.Debug.config with the following:

<?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转换中所指定. 为什么未考虑定位器条件"?

The result will show two <configSections /> elements, the one containing "mySection" being the first, as specified in the InsertBefore Transform. Why was the Locator Condition not taken into account?

推荐答案

因此,面对相同的问题后,我想出了一个解决方案.它既不漂亮也不优雅,但是可以工作. (至少在我的机器上)

So after facing the same issue, I came up with a solution. It's not pretty nor elegant, but it works. (At least on my machine)

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

I just split the logic into 3 different statements. First, I add an empty configSections at the correct position (first). Then I insert the new config to the last configSections, which would be the new one if it is the only one, or a previously existing one otherwise. Lastly I remove any empty configSections elemnt which might exist. I'm using RemoveAll for no good reason, you should probably use 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的空匹配集,因为那会让我做一些有趣的事情,例如

The question which still remains unanswered is why Locator conditions are not taken into account for InsertBefore. Or why I can't handle an empty match set for InsertBefore, because that would allowed me to do fun things such as

//configuration/*[position()=1 and not(local-name()='configSections')]

说实话,这是我要实现的目标的一种更清晰的方法.

Which to be honest is a much clearer way of doing what I want to achieve.

这篇关于XDT转换:InsertBefore-定位条件被忽略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆