GendoIkari GendoIkari - 3 months ago 30
ASP.NET (C#) Question

How to replace attributes in XML transforms without the name attribute

I am using SlowCheetah to transform my Log4Net files when I publish. However, it can't seem to distinguish between the attributes in different appender sections.

My Log4Net.config looks basically like this:

<?xml version="1.0" encoding="utf-8" ?>

<log4net>
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="DevEmail" />
<from value="DevEmail" />
<subject value="Dev Warning" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Time: %date%newlineHost: %property{log4net:HostName}%newlineClass: %logger%newlineUser: %property{user}%newlineMessage: %message%newline%newline%newline" />
</layout>
<threshold value="WARN" />
</appender>

<appender name="FatalSmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="DevEmail" />
<from value="DevEmail" />
<subject value="Dev Fatal" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Time: %date%newlineHost: %property{log4net:HostName}%newlineClass: %logger%newlineUser: %property{user}%newlineMessage: %message%newline%newline%newline" />
</layout>
<threshold value="FATAL" />
</appender>
</log4net>


And my transform file looks like this:

<?xml version="1.0" encoding="utf-8" ?>

<log4net xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="ProductionEmail" xdt:Transform="SetAttributes" />
<from value="ProductionEmail" xdt:Transform="SetAttributes" />
<subject value="Production Warning" xdt:Transform="SetAttributes" />
</appender>

<appender name="FatalSmtpAppender" type="log4net.Appender.SmtpAppender">
<to value="ProductionEmail" xdt:Transform="SetAttributes" />
<from value="ProductionEmail" xdt:Transform="SetAttributes" />
<subject value="Production Fatal" xdt:Transform="SetAttributes" />
</appender>
</log4net>


The problem is that the transformed config has the same subject attribute value for both appenders; I guess when it hits the SetAttributes it can't tell which tag it's looking for, so it transforms all of them. What it the correct syntax to tell it to only find the elements within the same appender? I assume I need to use the xdt:Locator attribute, but I can't do Match(name) like I do for web.config because these elements don't have a name attribute. The appender element has a name attribute, but I don't know how to tell it to match based on the parent element's name.

I know that I could use replace on the appender node, with the match(Name), but then I would be replacing the entire node, including a bunch of elements such as the layout which I don't want to be transformed (and thus have multiple copy-pastes of the same code, which I would like to avoid).

Answer

I found the answer in this MSDN article: http://msdn.microsoft.com/en-us/library/dd465326.aspx.

I needed to use xdt:Locator="Match(name)" on the parent <appender> node, and then xdt:Transform on the child nodes. I had tried this previously but had used xdt:locator="Match(name)" instead of xdt:Locator="Match(name)"... The attribute is case sensitive.

Comments