<configSections />
要素を挿入するか、ノードの子がすでに存在する場合はその子を操作する必要があるweb.configファイルがあります。
すでに存在している場合は、再度挿入したくありません(明らかに、存在は1回しか許可されていないため)。
通常、これは問題にはなりませんが、次のようになります。
この要素が構成ファイルにある場合は、要素の最初の子要素である必要があります。
出典: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 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>
結果には、InsertBefore Transformで指定されているように、2つの<configSections />
要素が表示されます。1つは「mySection」を含む要素が最初です。ロケーター条件が考慮されなかったのはなぜですか?
それで、同じ問題に直面した後、私は解決策を思いつきました。かわいくもエレガントでもありませんが、機能します。 (少なくとも私のマシンでは)
ロジックを3つの異なるステートメントに分割しました。まず、空のconfigSectionsを正しい位置(最初)に追加します。次に、新しい構成を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)" />
まだ答えられていない質問は、InsertBeforeでロケーター条件が考慮されない理由です。または、InsertBeforeの空の一致セットを処理できない理由は、次のような楽しいことができるためです。
//configuration/*[position()=1 and not(local-name()='configSections')]
正直に言うと、私が達成したいことを行うためのはるかに明確な方法です。