1

I want to create in an app - coded with C# - a copy of the actual element of a XMLReader object by using a XMLDocument instance.

The purpose is to get a copy of the actual reader element, so i can read the inner XML from the actual XML element without moving in the original reader.

When i try to load the reader into the XMLDocument i get the error "The document already has a 'DocumentElement' node.".

Any help would be appreciated.

XmlDocument xmlDocument = new XmlDocument();
MemoryStream streamFromReader = new MemoryStream();
xmlDocument.Load(reader); //Here i get the error
xmlDocument.Save(streamFromReader);
streamFromReader.Position = 0;
XmlReader copyReader = XmlReader.Create(streamFromReader);
sb.Append(copyReader.ReadInnerXml());
copyReader.Close();
Patrick Pirzer
  • 1,649
  • 3
  • 22
  • 49
  • What is the current position of the `XmlReader`? Can it be that it reads an element and errors when reading a sibling on the same level? – Markus Jul 22 '22 at 13:21
  • I think you should use `ReadSubtree()` method. – Alexander Petrov Jul 22 '22 at 13:26
  • Thank You Alexander. I tried this already and it moves the cursor in the original reader. XMLReader is not funny and normally - since the introduction of XMLDocument - i try to avoid it. – Patrick Pirzer Jul 22 '22 at 14:00
  • @Markus : The position is somewhere in the middle of the XML file. Under the actual element are three item nodes. After the actual element comes another one on the same level (depth). – Patrick Pirzer Jul 22 '22 at 14:09

2 Answers2

1

The problem is that the reader is already positioned somewhere in the middle of the XML file, e.g.:

<Parent>            <---- Position of the reader
  <Child></Child>
  <Child></Child>
</Parent>
<Parent>
  <Child></Child>
  <Child></Child>
</Parent>

The Load method starts to read the current node and also reads the siblings of the node. This leads to an invalid XML structure, because the document can only have one root element. The docs describe this behavior in the remarks section.

As for the original purpose of the code, I understand you want to perform a Peek (check the contents without advancing the reader) on the XmlReader. There are limited options to achieve this because an XmlReader operates forward-only. The answers to this question describe some options on how to read from an XmlReader without advancing it.

Markus
  • 20,838
  • 4
  • 31
  • 55
0

The answer of Markus helped me to get to the solution.

When the XMLReader is getting to an element which has subitems, i must get first the actual position within the file using the interface IXmlLineInfo.

IXmlLineInfo lineInfo = (IXmlLineInfo)reader;
int lineNumber = lineInfo.LineNumber;
int linePosition = lineInfo.LinePosition;

Then i create an instance of XmlTextReader, which reads the file to that position.

When the reminded position was arrived, the XmlTextReader contains the element and i can get the inner XML from it.

Stream stream = new MemoryStream(myFile.FileBytes);
XmlTextReader textReader = new XmlTextReader(stream);
while (textReader.LineNumber < lineNumber)
{
    textReader.Read();
}
string innerXml = textReader.ReadInnerXml());
textReader.Close();
Patrick Pirzer
  • 1,649
  • 3
  • 22
  • 49