Подтвердить что ты не робот

XDT Transform: InsertBefore - условие локатора игнорируется

У меня есть файл web.config, в котором мне нужно либо вставить элемент <configSections />, либо управлять дочерними элементами этого node, если он уже существует.
Если он уже существует, я не хочу вставлять его снова (очевидно, поскольку он разрешен только один раз).

Как правило, это не будет проблемой:

Если этот элемент находится в файле конфигурации, он должен быть первым дочерним элементом элемента.

Источник: 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, поэтому я не смогу использовать настраиваемое преобразование (как тот, который использует AppHarbor).

Есть ли какой-нибудь другой умный способ получить мой элемент в нужном месте, только если он еще не существует?

Чтобы проверить это, используйте тестер конфигурации адаптера AppHarbors. Замените 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. Почему условие Locator не принималось во внимание?

4b9b3361

Ответ 1

Поэтому, столкнувшись с той же проблемой, я придумал решение. Это не красиво или элегантно, но это работает. (По крайней мере, на моей машине)

Я просто разделил логику на 3 разных оператора. Во-первых, я добавляю пустые конфигурации в правильное положение (сначала). Затем я вставляю новую конфигурацию в last 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)" />

Вопрос, который по-прежнему остается без ответа, заключается в том, что условия Locator не учитываются для InsertBefore. Или почему я не могу обработать пустой набор совпадений для InsertBefore, потому что это позволило бы мне делать такие забавные вещи, как

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

Честно говоря, это гораздо более ясный способ сделать то, что я хочу достичь.