XDocument or XElement parsing of XML element containing namespaces

Ray Hayes picture Ray Hayes · Aug 2, 2009 · Viewed 11.7k times · Source

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..

Answer

Soonts picture Soonts · Aug 27, 2010

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 );
}