I am try to read the following string, captured from a log4net UdpAppender.
<log4net:event logger="TestingTransmitter.Program"
timestamp="2009-08-02T17:50:18.928+01:00"
level="ERROR"
thread="9"
domain="TestingTransmitter.vshost.exe"
username="domain\user">
<log4net:message>Log entry 103</log4net:message>
<log4net:properties>
<log4net:data name="log4net:HostName" value="machine" />
</log4net:properties>
</log4net:event>
When trying to XElement.Parse or XDocument.Parse the content, it throws an exception:
'log4net' is an undeclared namespace.
Line 1, position 2.
I know I can search and replace "log4net:" in the original string and remove it, allowing me to parse the XML successfully, but is there a better way? This is the complete data captured (reformatted to allow reading), there are no xml namespace declarations made or removed..
First, create an instance of XmlNamespaceManager class, and add your namespaces to that, e.g.
XmlNamespaceManager mngr = new XmlNamespaceManager( new NameTable() );
mngr.AddNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
mngr.AddNamespace( "xsd", "http://www.w3.org/2001/XMLSchema" );
To parse an XML string using those namespace mappings, call the following function, passing the instance of XmlNamespaceManager with the namespaces you've added to it:
/// <summary>Same as XElement.Parse(), but supports XML namespaces.</summary>
/// <param name="strXml">A String that contains XML.</param>
/// <param name="mngr">The XmlNamespaceManager to use for looking up namespace information.</param>
/// <returns>An XElement populated from the string that contains XML.</returns>
public static XElement ParseElement( string strXml, XmlNamespaceManager mngr )
{
XmlParserContext parserContext = new XmlParserContext( null, mngr, null, XmlSpace.None );
XmlTextReader txtReader = new XmlTextReader( strXml, XmlNodeType.Element, parserContext );
return XElement.Load( txtReader );
}
You really only have two options:
- Strip "log4net:" from the XML, as you suggested;
- Modify the XML to declare the namespace, probably most easily accomplished by wrapping the fragment (via StringBuilder) in a root element that has the declaration.
Strictly speaking, your example is malformed XML -- it's no surprise XDocument / XElement won't parse it.
you can use something like that:
<event xmlns="http://..." >
<message xmlns="http://...">...</message>
</event>