|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis article will show you how to process XML sub-trees when using BackgroundRecently, in an application, I had the need to log all XML messages exchanged with service providers. Being services implemented over the POX/REST (Plain Old XML/REpresentational State Transfer) protocol, I had the disadvantage of not being able to take advantage of the SOAP implementation in the .NET framework but, because I had to do it myself, I would have some control over the messages. Part of the message content belonged to the protocol implemented by the service provider (something like SOAP), and only a small part of it was service specific content. The service clients use DTOs (Data Transfer Objects) which were serialized using To make it more difficult to tamper with message content and to gain some performance, I opted by not using Because the messages were being handed out to XML sub-tree processingThe requirement looked simple; guarantee that each element of the XML sub-tree readingTo implement XML sub-tree reading, I opted on building a I opted also to implement public class XmlSubtreeReader : System.Xml.XmlReader,
System.IDisposable
{
public XmlSubtreeReader(System.Xml.XmlReader
wrappedReader) : base()
{
...
}
}
To guarantee that the recently created public override bool Read()
{
switch (this.readerState)
{
case XmlSubtreeReader.State.Initial:
{
this.readerState =
XmlSubtreeReader.State.Interactive;
this.ProcessNamespaces();
return true;
}
case XmlSubtreeReader.State.Interactive:
{
break;
}
case XmlSubtreeReader.State.PopNamespaceScope:
{
this.namespaceManager.PopScope();
goto case
XmlSubtreeReader.State.ClearNamespaceAttributes;
}
case XmlSubtreeReader.State.ClearNamespaceAttributes:
{
this.namespaceAttributeCount = 0;
this.readerState =
XmlSubtreeReader.State.Interactive;
break;
}
case XmlSubtreeReader.State.Error:
case XmlSubtreeReader.State.EndOfFile:
case XmlSubtreeReader.State.Closed:
default:
{
return false;
}
}
this.currentNamespaceAttribute = -1;
this.wrappedReader.MoveToElement();
if ((this.wrappedReader.Depth == this.initialDepth) &&
((this.wrappedReader.NodeType ==
System.Xml.XmlNodeType.EndElement)
|| ((this.wrappedReader.NodeType ==
System.Xml.XmlNodeType.Element)
&& this.wrappedReader.IsEmptyElement)))
{
this.readerState = XmlSubtreeReader.State.EndOfFile;
return false;
}
if (this.wrappedReader.Read())
{
this.ProcessNamespaces();
return true;
}
return false;
}
On the other hand, when closing the public override void Close()
{
if (this.readerState !=
XmlSubtreeReader.State.Closed)
{
while (this.readerState !=
XmlSubtreeReader.State.EndOfFile)
{
this.Skip();
}
this.wrappedReader.Skip();
this.readerState = XmlSubtreeReader.State.Closed;
}
}
XML sub-tree writingTo implement XML sub-tree writing, I opted on building a For the same reasons as with the reader, I opted on implementing public class XmlSubtreeWriter : System.Xml.XmlReader,
System.IDisposable
{
public XmlSubtreeWriter(System.Xml.XmlWriter
wrappedWriter) : base()
{
...
}
}
To guarantee that the recently created public override void WriteStartElement(string prefix,
string localName, string ns)
{
CheckWrite();
this.depth++;
this.wrappedWriter.WriteStartElement(prefix, localName, ns);
this.currentState = this.wrappedWriter.WriteState;
}
The In the same way, the As in sub-tree reading, when closing the public override void Close()
{
this.CompleteAll();
this.currentState = System.Xml.WriteState.Closed;
this.Flush();
}
|
|||||||||||||||||||||||||||||||||||