简体   繁体   中英

How does XDocument.Load(Stream) detect end of XML message?

Im reading a XDocument from a TcpClient stream. While implementing, I was wondering how the XDocument.Load(Stream) knows when the document is completed?

Several ideas crossed my mind, like received stream end or no more Bytes available. But now it Looks more that the Load() completes when the EndElement is received.

Anybody knows how the Load(Stream) internals work?

Thanks Tom

It's easy to prove that it reads past the end element - you just need to create an XML file which contains data after the end element, making it invalid:

<root>
  <child />
</root>

More stuff

If you load that, you'll get an exception like this:

Unhandled Exception: System.Xml.XmlException: Data at the root level is invalid.
Line 5, position 1.

I would strongly expect it to read to the end of the stream.

Taken from the decompiled assembly:

[__DynamicallyInvokable]
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public static XDocument Load(Stream stream)
    {
      return XDocument.Load(stream, LoadOptions.None);
    }

    [__DynamicallyInvokable]
    public static XDocument Load(Stream stream, LoadOptions options)
    {
      XmlReaderSettings xmlReaderSettings = XNode.GetXmlReaderSettings(options);
      using (XmlReader reader = XmlReader.Create(stream, xmlReaderSettings))
        return XDocument.Load(reader, options);
    }

Internally it creates a XML Reader and calls the XDocument.Load Method (XmlReader) XML Reader is created by Stream by reading it to the end (by following the implementations around)

Updated : I misread XDocument as XmlDocument. The answer is still valid. You read until the end of the stream as both XDocument and XmlDocument chain down to XmlTextReaderImpl.InitStreamInput which is where stream reading occurs. Once you reach the end of the stream you begin processing the data. If parsing fails you'll get an XmlException, but this occurs after all stream reading is complete.

If you walk through the .NET Reference Source you'll see the following (for reading from a stream):

XDocument.Load(Stream), calls XmlReader.Create, which instantiates XmlReaderSettings and calls CreateReader on that instance, which instantiates XmlTextReaderImpl, which calls FinishInitStream on that instance, which calls InitStreamInput. This is where the bulk of the work happens and where you can find checks for End of File that are based on # of characters read.

Note: XmlDocument.Load(Stream) follows a similar approach that calls InitStreamInput (so the same stream reading code is used)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM