简体   繁体   中英

Web.config transformation locator condition or xpath not working with multiple attributes

I'm using Microsoft's XDT library to transform my web.config files and discovered that Locator is not working as expected. Using the example below, I would expect that both the attributes are set and the converter node is inserted in all three appenders, but only the attributes are updated in all three. The converter node is only inserted into the first appender. How do I get it to insert into all three log4net appender nodes?

I've tried switching to XPath, but it only throws errors. A working example would be nice, because every example I've followed so far seems to fail with an error.

Test site: https://webconfigtransformationtester.apphb.com/

For example:

Web.config

<?xml version="1.0"?>
<configuration>
  <log4net>
    <appender name="App1">
      <layout>
        <conversionPattern value="foo"/>
      </layout>
    </appender>
    <appender name="App2">
      <layout>
        <conversionPattern value="foo"/>
      </layout>
    </appender>
    <appender name="App3">
      <layout>
        <conversionPattern value="foo"/>
      </layout>
    </appender>
  </log4net>
</configuration>

Web.Debug.config

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <log4net>
    <appender xdt:Locator="Condition(@name='App1' or @name='App2' or @name='App3')">
      <layout>
        <conversionPattern value="bar" xdt:Transform="SetAttributes" />
        <converter xdt:Transform="Insert">
          <name value="Default" />
          <type value="Common.DefaultConverter, Common" />
        </converter>
      </layout>
    </appender>
  </log4net>
</configuration>

Results:

<?xml version="1.0"?>
<configuration>
  <log4net>
    <appender name="App1">
      <layout>
        <conversionPattern value="bar" />
      <converter><name value="Default" /><type value="Common.DefaultConverter, Common" /></converter></layout>
    </appender>
    <appender name="App2">
      <layout>
        <conversionPattern value="bar" />
      </layout>
    </appender>
    <appender name="App3">
      <layout>
        <conversionPattern value="bar" />
      </layout>
    </appender>
  </log4net>
</configuration>

It turns out that it was designed this way. Only attributes are applied to all target nodes. To work around the issue, download the code from here and add the following lines:

In XmlElementContext, add the property:

   internal bool HasLocator
    {
        get
        {
            return this.LocatorAttribute != null || (this.parentContext != null && this.parentContext.HasLocator);
        }
    }

In XmlTransform modify this line, adding the call to HasLocator:

if (ApplyTransformToAllTargetNodes || context.HasLocator) {

This code will determine if a "Locator" has been set within the current context or any parent context (like in my example) and apply all transforms to all target nodes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM