XDocument or XElement parsing of XML element conta

2019-02-08 09:19发布

问题:

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

回答1:

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


回答2:

You really only have two options:

  1. Strip "log4net:" from the XML, as you suggested;
  2. 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.



回答3:

you can use something like that:

<event xmlns="http://..." >
    <message xmlns="http://...">...</message>
</event>