XmlSubtreeWriter
using System;
using System.Threading;
using System.Xml;
namespace Castle.Components.DictionaryAdapter.Xml
{
public class XmlSubtreeWriter : XmlWriter
{
private readonly IXmlNode node;
private XmlWriter rootWriter;
private XmlWriter childWriter;
private WriteState state;
private int depth;
private XmlWriter RootWriter => rootWriter ?? (rootWriter = node.WriteAttributes());
private XmlWriter ChildWriter => childWriter ?? (childWriter = node.WriteChildren());
private bool IsInRootAttribute => state == WriteState.Attribute;
private bool IsInRoot => depth > 0;
private bool IsInChild => depth > 1;
public override WriteState WriteState {
get {
if (!IsInRoot || state != WriteState.Content)
return state;
return childWriter.WriteState;
}
}
public XmlSubtreeWriter(IXmlNode node)
{
if (node == null)
throw Error.ArgumentNull("node");
this.node = node;
}
protected override void Dispose(bool managed)
{
try {
if (managed) {
Reset(WriteState.Closed);
DisposeWriter(ref rootWriter);
DisposeWriter(ref childWriter);
}
} finally {
base.Dispose(managed);
}
}
private void DisposeWriter(ref XmlWriter writer)
{
Interlocked.Exchange<XmlWriter>(ref writer, (XmlWriter)null)?.Close();
}
public override void WriteStartDocument(bool standalone)
{
WriteStartDocument();
}
public override void WriteStartDocument()
{
RequireState(WriteState.Start);
state = WriteState.Prolog;
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
RequireState(WriteState.Start, WriteState.Prolog);
state = WriteState.Prolog;
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
try {
if (IsInRoot) {
ChildWriter.WriteStartElement(prefix, localName, ns);
state = WriteState.Content;
} else {
RequireState(WriteState.Start, WriteState.Prolog);
node.Clear();
state = WriteState.Element;
}
depth++;
} catch {
Reset(WriteState.Error);
throw;
}
}
private void WriteEndElement(Action<XmlWriter> action)
{
try {
if (IsInChild) {
action.Invoke(ChildWriter);
state = WriteState.Content;
} else {
RequireState(WriteState.Element, WriteState.Content);
state = WriteState.Prolog;
}
depth--;
} catch {
Reset(WriteState.Error);
throw;
}
}
public unsafe override void WriteEndElement()
{
WriteEndElement(<>c.<>9__25_0 ?? (<>c.<>9__25_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))));
}
public unsafe override void WriteFullEndElement()
{
WriteEndElement(<>c.<>9__26_0 ?? (<>c.<>9__26_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))));
}
private void WriteAttribute(Action<XmlWriter> action, WriteState entryState, WriteState exitState)
{
try {
if (IsInChild)
action.Invoke(ChildWriter);
else {
RequireState(entryState);
action.Invoke(RootWriter);
state = exitState;
}
} catch {
Reset(WriteState.Error);
throw;
}
}
public unsafe override void WriteStartAttribute(string prefix, string localName, string ns)
{
<>c__DisplayClass28_0 <>c__DisplayClass28_;
WriteAttribute(new Action<XmlWriter>((object)<>c__DisplayClass28_, (IntPtr)(void*)), WriteState.Element, WriteState.Attribute);
}
public unsafe override void WriteEndAttribute()
{
WriteAttribute(<>c.<>9__29_0 ?? (<>c.<>9__29_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))), WriteState.Attribute, WriteState.Element);
}
private void WriteElementOrAttributeContent(Action<XmlWriter> action)
{
try {
if (IsInChild)
action.Invoke(ChildWriter);
else if (IsInRootAttribute) {
action.Invoke(RootWriter);
} else {
RequireState(WriteState.Element, WriteState.Content);
action.Invoke(ChildWriter);
state = WriteState.Content;
}
} catch {
Reset(WriteState.Error);
throw;
}
}
public unsafe override void WriteString(string text)
{
<>c__DisplayClass31_0 <>c__DisplayClass31_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass31_, (IntPtr)(void*)));
}
public unsafe override void WriteCharEntity(char ch)
{
<>c__DisplayClass32_0 <>c__DisplayClass32_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass32_, (IntPtr)(void*)));
}
public unsafe override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
<>c__DisplayClass33_0 <>c__DisplayClass33_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass33_, (IntPtr)(void*)));
}
public unsafe override void WriteEntityRef(string name)
{
<>c__DisplayClass34_0 <>c__DisplayClass34_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass34_, (IntPtr)(void*)));
}
public unsafe override void WriteChars(char[] buffer, int index, int count)
{
<>c__DisplayClass35_0 <>c__DisplayClass35_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass35_, (IntPtr)(void*)));
}
public unsafe override void WriteBase64(byte[] buffer, int index, int count)
{
<>c__DisplayClass36_0 <>c__DisplayClass36_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass36_, (IntPtr)(void*)));
}
public unsafe override void WriteRaw(string data)
{
<>c__DisplayClass37_0 <>c__DisplayClass37_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass37_, (IntPtr)(void*)));
}
public unsafe override void WriteRaw(char[] buffer, int index, int count)
{
<>c__DisplayClass38_0 <>c__DisplayClass38_;
WriteElementOrAttributeContent(new Action<XmlWriter>((object)<>c__DisplayClass38_, (IntPtr)(void*)));
}
private void WriteElementContent(Action<XmlWriter> action)
{
try {
RequireState(WriteState.Element, WriteState.Content);
action.Invoke(ChildWriter);
state = WriteState.Content;
} catch {
Reset(WriteState.Error);
throw;
}
}
public unsafe override void WriteCData(string text)
{
<>c__DisplayClass40_0 <>c__DisplayClass40_;
WriteElementContent(new Action<XmlWriter>((object)<>c__DisplayClass40_, (IntPtr)(void*)));
}
public unsafe override void WriteProcessingInstruction(string name, string text)
{
<>c__DisplayClass41_0 <>c__DisplayClass41_;
WriteElementContent(new Action<XmlWriter>((object)<>c__DisplayClass41_, (IntPtr)(void*)));
}
public unsafe override void WriteComment(string text)
{
<>c__DisplayClass42_0 <>c__DisplayClass42_;
WriteElementContent(new Action<XmlWriter>((object)<>c__DisplayClass42_, (IntPtr)(void*)));
}
public unsafe override void WriteWhitespace(string ws)
{
<>c__DisplayClass43_0 <>c__DisplayClass43_;
WriteElementContent(new Action<XmlWriter>((object)<>c__DisplayClass43_, (IntPtr)(void*)));
}
private void WithWriters(Action<XmlWriter> action, bool worksIfClosed = false, WriteState? resetTo = default(WriteState?))
{
try {
if (!worksIfClosed)
RequireNotClosed();
if (rootWriter != null)
action.Invoke(rootWriter);
if (childWriter != null)
action.Invoke(childWriter);
if (resetTo.get_HasValue())
Reset(resetTo.get_Value());
} catch {
Reset(WriteState.Error);
throw;
}
}
public unsafe override void Flush()
{
WithWriters(<>c.<>9__45_0 ?? (<>c.<>9__45_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))), false, null);
}
public unsafe override void WriteEndDocument()
{
WithWriters(<>c.<>9__46_0 ?? (<>c.<>9__46_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))), false, WriteState.Start);
}
public unsafe override void Close()
{
WithWriters(<>c.<>9__47_0 ?? (<>c.<>9__47_0 = new Action<XmlWriter>((object)<>c.<>9, (IntPtr)(void*))), true, WriteState.Closed);
}
public override string LookupPrefix(string ns)
{
try {
string text;
return (childWriter != null && (text = childWriter.LookupPrefix(ns)) != null) ? text : ((rootWriter != null && (text = rootWriter.LookupPrefix(ns)) != null) ? text : null);
} catch {
Reset(WriteState.Error);
throw;
}
}
private void RequireNotClosed()
{
if (state == WriteState.Closed || state == WriteState.Error)
throw Error.InvalidOperation();
}
private void RequireState(WriteState state)
{
if (this.state != state)
throw Error.InvalidOperation();
}
private void RequireState(WriteState state1, WriteState state2)
{
if (state != state1 && state != state2)
throw Error.InvalidOperation();
}
private void Reset(WriteState state)
{
depth = 0;
this.state = state;
}
}
}