#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #endregion using System; using System.IO; using System.Text; using System.Xml; using log4net.Util; using log4net.Core; namespace log4net.Layout { /// /// Layout that formats the log events as XML elements. /// /// /// /// This is an abstract class that must be subclassed by an implementation /// to conform to a specific schema. /// /// /// Deriving classes must implement the method. /// /// /// Nicko Cadell /// Gert Driesen abstract public class XmlLayoutBase : LayoutSkeleton { #region Protected Instance Constructors /// /// Protected constructor to support subclasses /// /// /// /// Initializes a new instance of the class /// with no location info. /// /// protected XmlLayoutBase() : this(false) { IgnoresException = false; } /// /// Protected constructor to support subclasses /// /// /// /// The parameter determines whether /// location information will be output by the layout. If /// is set to true, then the /// file name and line number of the statement at the origin of the log /// statement will be output. /// /// /// If you are embedding this layout within an SMTPAppender /// then make sure to set the LocationInfo option of that /// appender as well. /// /// protected XmlLayoutBase(bool locationInfo) { IgnoresException = false; m_locationInfo = locationInfo; } #endregion Protected Instance Constructors #region Public Instance Properties /// /// Gets a value indicating whether to include location information in /// the XML events. /// /// /// true if location information should be included in the XML /// events; otherwise, false. /// /// /// /// If is set to true, then the file /// name and line number of the statement at the origin of the log /// statement will be output. /// /// /// If you are embedding this layout within an SMTPAppender /// then make sure to set the LocationInfo option of that /// appender as well. /// /// public bool LocationInfo { get { return m_locationInfo; } set { m_locationInfo = value; } } /// /// The string to replace characters that can not be expressed in XML with. /// /// /// Not all characters may be expressed in XML. This property contains the /// string to replace those that can not with. This defaults to a ?. Set it /// to the empty string to simply remove offending characters. For more /// details on the allowed character ranges see http://www.w3.org/TR/REC-xml/#charsets /// Character replacement will occur in the log message, the property names /// and the property values. /// /// /// public string InvalidCharReplacement { get {return m_invalidCharReplacement;} set {m_invalidCharReplacement=value;} } #endregion #region Implementation of IOptionHandler /// /// Initialize layout options /// /// /// /// This is part of the delayed object /// activation scheme. The method must /// be called on this object after the configuration properties have /// been set. Until is called this /// object is in an undefined state and must not be used. /// /// /// If any of the configuration properties are modified then /// must be called again. /// /// override public void ActivateOptions() { // nothing to do } #endregion Implementation of IOptionHandler #region Override implementation of LayoutSkeleton /// /// Gets the content type output by this layout. /// /// /// As this is the XML layout, the value is always "text/xml". /// /// /// /// As this is the XML layout, the value is always "text/xml". /// /// override public string ContentType { get { return "text/xml"; } } /// /// Produces a formatted string. /// /// The event being logged. /// The TextWriter to write the formatted event to /// /// /// Format the and write it to the . /// /// /// This method creates an that writes to the /// . The is passed /// to the method. Subclasses should override the /// method rather than this method. /// /// override public void Format(TextWriter writer, LoggingEvent loggingEvent) { if (loggingEvent == null) { throw new ArgumentNullException("loggingEvent"); } XmlTextWriter xmlWriter = new XmlTextWriter(new ProtectCloseTextWriter(writer)); xmlWriter.Formatting = Formatting.None; xmlWriter.Namespaces = false; // Write the event to the writer FormatXml(xmlWriter, loggingEvent); xmlWriter.WriteWhitespace(SystemInfo.NewLine); // Close on xmlWriter will ensure xml is flushed // the protected writer will ignore the actual close xmlWriter.Close(); } #endregion Override implementation of LayoutSkeleton #region Protected Instance Methods /// /// Does the actual writing of the XML. /// /// The writer to use to output the event to. /// The event to write. /// /// /// Subclasses should override this method to format /// the as XML. /// /// abstract protected void FormatXml(XmlWriter writer, LoggingEvent loggingEvent); #endregion Protected Instance Methods #region Private Instance Fields /// /// Flag to indicate if location information should be included in /// the XML events. /// private bool m_locationInfo = false; /// /// The string to replace invalid chars with /// private string m_invalidCharReplacement="?"; #endregion Private Instance Fields } }