Web Config Transforms: Insert If Not Exists

XpathWeb ConfigWeb Config-Transform

Xpath Problem Overview


I would like to apply a transformation if and only if a matched element does not exist in the target. Trying various xpath expressions using http://webconfigtransformationtester.apphb.com/ but no luck so far.

E.g. if the target web.config looks like this:

<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
</configuration>

then the output should look like this:

<configuration>
  <connectionStrings>
    <add name="MyCs" provider="System.Data.SqlClient" connectionString="" />
    <add name="SomeOtherCs" provider="System.Data.SqlClient" connectionString="" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" />
  </system.web>
</configuration>

But if the target looks like this:

<configuration>
  <connectionStrings>
    <add name="MyCs" provider="System.Data.IChangedIt" connectionString="my connection string here" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" />
  </system.web>
</configuration>

then the result of the transformation should look like this:

<configuration>
  <connectionStrings>
    <add name="MyCs" provider="System.Data.IChangedIt" connectionString="my connection string here" />
    <add name="SomeOtherCs" provider="System.Data.SqlClient" connectionString="" />   
  </connectionStrings>
  <system.web>
    <compilation debug="true" />
  </system.web>
</configuration>

In other words, I just want to add the named connection string to configuration but let the administrator fill it in with his own values. I thought it would as simple as xdt:Transform="Insert" xdt:Locator="XPath(count(/configuration/connectionStrings)=0)" (to add a cs config section if none existed) but apparently not.

Xpath Solutions


Solution 1 - Xpath

Use xdt:Transform="InsertIfMissing" with the XmlTransform task in VS2012. It doesn't look like Microsoft has updated their documentation to reflect this yet.

Solution 2 - Xpath

In my case xdt:Transform="InsertIfMissing" did not work without xdt:Locator="Match(name)"

Solution 3 - Xpath

Try this alternative transformation for xdt:Transform="InsertIfMissing" :

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <nodeToInsertIfMissing xdt:Transform="Insert" />
  <nodeToInsertIfMissing xdt:Transform="Remove" xdt:Locator="XPath(/configuration/nodeToInsertIfMissing[2])" />
</configuration>

It should works following MSDN documentation:

Insert - adds the element that is defined in the transform file as a sibling to the selected element or elements. The new element is added at the end of any collection.

So, if the node already exists, we add the second one and then remove this node (2nd). Otherwise, we add the new, unique node but remove operation will fail.

Note: It seems not working with NuGet *.(un)install.xdt transformation. InsertIfMissing too.

Solution 4 - Xpath

Confirmed working in VS2015 and Package Manager Console Host Version 3.4.4.1321 (you can find this when you open the Package Manager Console).

This will insert if 'configuration\connectionStrings\add@name' does not exist.

The app.config.install.xdt:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
	<connectionStrings xdt:Transform="InsertIfMissing">
		<add name="MyCs" provider="System.Data.SqlClient" connectionString="" xdt:Transform="InsertIfMissing" xdt:Locator="Match(name)"/>
	</connectionStrings>
</configuration>

The .nuspec file:

<files>
    <file src="app.config.install.xdt" target="content\app.config.install.xdt" />

Solution 5 - Xpath

Use xdt:Transform="Remove" followed by xdt:Transform="Insert" transforms. The xdt:Transform="InsertIfMissing" suggested elsewhere did not work for me, looks like its version specific.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJo&#227;o Bragan&#231;aView Question on Stackoverflow
Solution 1 - XpathADW334034View Answer on Stackoverflow
Solution 2 - XpathGerardBeckerlegView Answer on Stackoverflow
Solution 3 - XpathKryszalView Answer on Stackoverflow
Solution 4 - XpathOzBobView Answer on Stackoverflow
Solution 5 - XpathTaras AleninView Answer on Stackoverflow