Replacing entire node using web.config transforms resulting in error

1.6k Views Asked by At

I can't quite figure out what I'm doing wrong here. I have a node in a web config:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    ...
    <runtime>
       <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
           <dependentAssembly>
              <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
              <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
           </dependentAssembly>
           ....

and I want to replace this with:

<dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
    <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>

using MsBuild TransformXml. I can't quite figure out the correct syntax for the xdt attributes though. The following (which looks correct to me) :

<dependentAssembly xdt:Transform="Replace" 
                                    xdt:Locator="Condition(param/@name='Newtonsoft.Json'">
    <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
    <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>

Is resulting in an error:

XmlNodeException : Transform and Locator attributes must contain only a type name, or a type name followed by a list of attributes in parentheses.

what am I missing here?

I can't alter the original BTW, this must be done using transforms.

2

There are 2 best solutions below

0
On BEST ANSWER

Attribute name='Newtonsoft.Json' is located in a parent element named assemblyIdentity, so I'm not sure why param/@name. The correct XPath expression to test if child element named -ignoring namespaces- 'assemblyIdentity' has attribute name value equals 'Newtonsoft.Json' would be as follow :

xdt:Locator="Condition(*[local-name()='assemblyIdentity']/@name='Newtonsoft.Json')"
0
On

The problem basically the name space. Define this namespace in your xdt file.

<configuration xmlns:asm="urn:schemas-microsoft-com:asm.v1" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

Use the new namespace like this:

<asm:assemblyBinding>
  <asm:dependentAssembly xdt:Transform="Replace" xdt:Locator="Condition(asm:assemblyIdentity/@name='Newtonsoft.Json')" >
    <asm:assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
    <asm:bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
  </asm:dependentAssembly>
</asm:assemblyBinding>

I think this is a bit more elegant than local-name() version.