|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.IO;
using System.Collections;
using System.Text;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.Xml
{
using System;
internal abstract class XmlBaseWriter : XmlDictionaryWriter
{
private XmlNodeWriter _writer;
private NamespaceManager _nsMgr;
private Element[] _elements;
private int _depth;
private string _attributeLocalName;
private string _attributeValue;
private bool _isXmlAttribute;
private bool _isXmlnsAttribute;
private WriteState _writeState;
private DocumentState _documentState;
private byte[] _trailBytes;
private int _trailByteCount;
private XmlStreamNodeWriter _nodeWriter;
private bool _inList;
private const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/";
private const string xmlNamespace = "http://www.w3.org/XML/1998/namespace";
private static string[] s_prefixes = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
protected XmlBaseWriter()
{
_nsMgr = new NamespaceManager();
_writeState = WriteState.Start;
_documentState = DocumentState.None;
}
protected void SetOutput(XmlStreamNodeWriter writer)
{
_inList = false;
_writer = writer;
_nodeWriter = writer;
_writeState = WriteState.Start;
_documentState = DocumentState.None;
_nsMgr.Clear();
if (_depth != 0)
{
_elements = null;
_depth = 0;
}
_attributeLocalName = null;
_attributeValue = null;
}
public override void Flush()
{
if (IsClosed)
ThrowClosed();
_writer.Flush();
}
public override void Close()
{
if (IsClosed)
return;
try
{
FinishDocument();
AutoComplete(WriteState.Closed);
_writer.Flush();
}
finally
{
_nsMgr.Close();
if (_depth != 0)
{
_elements = null;
_depth = 0;
}
_attributeValue = null;
_attributeLocalName = null;
_nodeWriter.Close();
}
}
protected bool IsClosed
{
get { return _writeState == WriteState.Closed; }
}
protected void ThrowClosed()
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlWriterClosed)));
}
public override string XmlLang
{
get
{
return _nsMgr.XmlLang;
}
}
public override XmlSpace XmlSpace
{
get
{
return _nsMgr.XmlSpace;
}
}
public override WriteState WriteState
{
get
{
return _writeState;
}
}
public override void WriteXmlnsAttribute(string prefix, string ns)
{
if (IsClosed)
ThrowClosed();
if (ns == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns");
if (_writeState != WriteState.Element)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteXmlnsAttribute", WriteState.ToString())));
if (prefix == null)
{
prefix = _nsMgr.LookupPrefix(ns);
if (prefix == null)
{
GeneratePrefix(ns, null);
}
}
else
{
_nsMgr.AddNamespaceIfNotDeclared(prefix, ns, null);
}
}
public override void WriteXmlnsAttribute(string prefix, XmlDictionaryString ns)
{
if (IsClosed)
ThrowClosed();
if (ns == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns");
if (_writeState != WriteState.Element)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteXmlnsAttribute", WriteState.ToString())));
if (prefix == null)
{
prefix = _nsMgr.LookupPrefix(ns.Value);
if (prefix == null)
{
GeneratePrefix(ns.Value, ns);
}
}
else
{
_nsMgr.AddNamespaceIfNotDeclared(prefix, ns.Value, ns);
}
}
private void StartAttribute(ref string prefix, string localName, string ns, XmlDictionaryString xNs)
{
if (IsClosed)
ThrowClosed();
if (_writeState == WriteState.Attribute)
WriteEndAttribute();
if (localName == null || (localName.Length == 0 && prefix != "xmlns"))
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName"));
if (_writeState != WriteState.Element)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteStartAttribute", WriteState.ToString())));
if (prefix == null)
{
if (ns == xmlnsNamespace && localName != "xmlns")
prefix = "xmlns";
else if (ns == xmlNamespace)
prefix = "xml";
else
prefix = string.Empty;
}
// Normalize a (prefix,localName) of (null, "xmlns") to ("xmlns", string.Empty).
if (prefix.Length == 0 && localName == "xmlns")
{
prefix = "xmlns";
localName = string.Empty;
}
_isXmlnsAttribute = false;
_isXmlAttribute = false;
if (prefix == "xml")
{
if (ns != null && ns != xmlNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlPrefixBoundToNamespace, "xml", xmlNamespace, ns), "ns"));
_isXmlAttribute = true;
_attributeValue = string.Empty;
_attributeLocalName = localName;
}
else if (prefix == "xmlns")
{
if (ns != null && ns != xmlnsNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlPrefixBoundToNamespace, "xmlns", xmlnsNamespace, ns), "ns"));
_isXmlnsAttribute = true;
_attributeValue = string.Empty;
_attributeLocalName = localName;
}
else if (ns == null)
{
// A null namespace means the namespace of the given prefix.
if (prefix.Length == 0)
{
// An empty prefix on an attribute means no namespace (not the default namespace)
ns = string.Empty;
}
else
{
ns = _nsMgr.LookupNamespace(prefix);
if (ns == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlUndefinedPrefix, prefix), "prefix"));
}
}
else if (ns.Length == 0)
{
// An empty namespace means no namespace; prefix must be empty
if (prefix.Length != 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlEmptyNamespaceRequiresNullPrefix), "prefix"));
}
else if (prefix.Length == 0)
{
// No prefix specified - try to find a prefix corresponding to the given namespace
prefix = _nsMgr.LookupAttributePrefix(ns);
// If we didn't find anything with the right namespace, generate one.
if (prefix == null)
{
// Watch for special values
if (ns.Length == xmlnsNamespace.Length && ns == xmlnsNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlSpecificBindingNamespace, "xmlns", ns)));
if (ns.Length == xmlNamespace.Length && ns == xmlNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlSpecificBindingNamespace, "xml", ns)));
prefix = GeneratePrefix(ns, xNs);
}
}
else
{
_nsMgr.AddNamespaceIfNotDeclared(prefix, ns, xNs);
}
_writeState = WriteState.Attribute;
}
public override void WriteStartAttribute(string prefix, string localName, string namespaceUri)
{
StartAttribute(ref prefix, localName, namespaceUri, null);
if (!_isXmlnsAttribute)
{
_writer.WriteStartAttribute(prefix, localName);
}
}
public override void WriteStartAttribute(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
StartAttribute(ref prefix, (localName != null ? localName.Value : null), (namespaceUri != null ? namespaceUri.Value : null), namespaceUri);
if (!_isXmlnsAttribute)
{
_writer.WriteStartAttribute(prefix, localName);
}
}
public override void WriteEndAttribute()
{
if (IsClosed)
ThrowClosed();
if (_writeState != WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteEndAttribute", WriteState.ToString())));
FlushBase64();
try
{
if (_isXmlAttribute)
{
if (_attributeLocalName == "lang")
{
_nsMgr.AddLangAttribute(_attributeValue);
}
else if (_attributeLocalName == "space")
{
if (_attributeValue == "preserve")
{
_nsMgr.AddSpaceAttribute(XmlSpace.Preserve);
}
else if (_attributeValue == "default")
{
_nsMgr.AddSpaceAttribute(XmlSpace.Default);
}
else
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlInvalidXmlSpace, _attributeValue)));
}
}
else
{
// XmlTextWriter specifically allows for other localNames
}
_isXmlAttribute = false;
_attributeLocalName = null;
_attributeValue = null;
}
if (_isXmlnsAttribute)
{
_nsMgr.AddNamespaceIfNotDeclared(_attributeLocalName, _attributeValue, null);
_isXmlnsAttribute = false;
_attributeLocalName = null;
_attributeValue = null;
}
else
{
_writer.WriteEndAttribute();
}
}
finally
{
_writeState = WriteState.Element;
}
}
private async Task WriteEndAttributeAsyncImpl()
{
await FlushBase64Async().ConfigureAwait(false);
try
{
if (_isXmlAttribute)
{
if (_attributeLocalName == "lang")
{
_nsMgr.AddLangAttribute(_attributeValue);
}
else if (_attributeLocalName == "space")
{
if (_attributeValue == "preserve")
{
_nsMgr.AddSpaceAttribute(XmlSpace.Preserve);
}
else if (_attributeValue == "default")
{
_nsMgr.AddSpaceAttribute(XmlSpace.Default);
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlInvalidXmlSpace, _attributeValue)));
}
}
else
{
// XmlTextWriter specifically allows for other localNames
}
_isXmlAttribute = false;
_attributeLocalName = null;
_attributeValue = null;
}
if (_isXmlnsAttribute)
{
_nsMgr.AddNamespaceIfNotDeclared(_attributeLocalName, _attributeValue, null);
_isXmlnsAttribute = false;
_attributeLocalName = null;
_attributeValue = null;
}
else
{
await _writer.WriteEndAttributeAsync().ConfigureAwait(false);
}
}
finally
{
_writeState = WriteState.Element;
}
}
public override void WriteComment(string text)
{
if (IsClosed)
ThrowClosed();
if (_writeState == WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteComment", WriteState.ToString())));
if (text == null)
{
text = string.Empty;
}
else if (text.IndexOf("--", StringComparison.Ordinal) != -1 || (text.Length > 0 && text[text.Length - 1] == '-'))
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlInvalidCommentChars), "text"));
}
StartComment();
FlushBase64();
_writer.WriteComment(text);
EndComment();
}
public override void WriteFullEndElement()
{
if (IsClosed)
ThrowClosed();
if (_writeState == WriteState.Attribute)
WriteEndAttribute();
if (_writeState != WriteState.Element && _writeState != WriteState.Content)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteFullEndElement", WriteState.ToString())));
AutoComplete(WriteState.Content);
WriteEndElement();
}
public override void WriteCData(string text)
{
if (IsClosed)
ThrowClosed();
if (_writeState == WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteCData", WriteState.ToString())));
if (text == null)
text = string.Empty;
if (text.Length > 0)
{
StartContent();
FlushBase64();
_writer.WriteCData(text);
EndContent();
}
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(string.Format(SRSerialization.XmlMethodNotSupported, "WriteDocType")));
}
private void StartElement(ref string prefix, string localName, string ns, XmlDictionaryString xNs)
{
if (IsClosed)
ThrowClosed();
if (_documentState == DocumentState.Epilog)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlOnlyOneRoot)));
if (localName == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName"));
if (localName.Length == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.InvalidLocalNameEmpty), "localName"));
if (_writeState == WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteStartElement", WriteState.ToString())));
FlushBase64();
AutoComplete(WriteState.Element);
Element element = EnterScope();
if (ns == null)
{
if (prefix == null)
prefix = string.Empty;
ns = _nsMgr.LookupNamespace(prefix);
if (ns == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlUndefinedPrefix, prefix), "prefix"));
}
else if (prefix == null)
{
prefix = _nsMgr.LookupPrefix(ns);
if (prefix == null)
{
prefix = string.Empty;
_nsMgr.AddNamespace(string.Empty, ns, xNs);
}
}
else
{
_nsMgr.AddNamespaceIfNotDeclared(prefix, ns, xNs);
}
element.Prefix = prefix;
element.LocalName = localName;
}
private void PreStartElementAsyncCheck(string prefix, string localName, string ns, XmlDictionaryString xNs)
{
if (IsClosed)
ThrowClosed();
if (_documentState == DocumentState.Epilog)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlOnlyOneRoot)));
if (localName == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName"));
if (localName.Length == 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.InvalidLocalNameEmpty), "localName"));
if (_writeState == WriteState.Attribute)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteStartElement", WriteState.ToString())));
}
private async Task StartElementAndWriteStartElementAsync(string prefix, string localName, string namespaceUri)
{
prefix = await StartElementAsync(prefix, localName, namespaceUri, null).ConfigureAwait(false);
await _writer.WriteStartElementAsync(prefix, localName).ConfigureAwait(false);
}
private async Task<string> StartElementAsync(string prefix, string localName, string ns, XmlDictionaryString xNs)
{
await FlushBase64Async().ConfigureAwait(false);
await AutoCompleteAsync(WriteState.Element).ConfigureAwait(false);
Element element = EnterScope();
if (ns == null)
{
if (prefix == null)
prefix = string.Empty;
ns = _nsMgr.LookupNamespace(prefix);
if (ns == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlUndefinedPrefix, prefix), "prefix"));
}
else if (prefix == null)
{
prefix = _nsMgr.LookupPrefix(ns);
if (prefix == null)
{
prefix = string.Empty;
_nsMgr.AddNamespace(string.Empty, ns, xNs);
}
}
else
{
_nsMgr.AddNamespaceIfNotDeclared(prefix, ns, xNs);
}
element.Prefix = prefix;
element.LocalName = localName;
return prefix;
}
public override void WriteStartElement(string prefix, string localName, string namespaceUri)
{
StartElement(ref prefix, localName, namespaceUri, null);
_writer.WriteStartElement(prefix, localName);
}
public override void WriteStartElement(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
StartElement(ref prefix, (localName != null ? localName.Value : null), (namespaceUri != null ? namespaceUri.Value : null), namespaceUri);
_writer.WriteStartElement(prefix, localName);
}
public override void WriteEndElement()
{
if (IsClosed)
ThrowClosed();
if (_depth == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidDepth, "WriteEndElement", _depth.ToString(CultureInfo.InvariantCulture))));
if (_writeState == WriteState.Attribute)
WriteEndAttribute();
FlushBase64();
if (_writeState == WriteState.Element)
{
_nsMgr.DeclareNamespaces(_writer);
_writer.WriteEndStartElement(true);
}
else
{
Element element = _elements[_depth];
_writer.WriteEndElement(element.Prefix, element.LocalName);
}
ExitScope();
_writeState = WriteState.Content;
}
private Element EnterScope()
{
_nsMgr.EnterScope();
_depth++;
if (_elements == null)
{
_elements = new Element[4];
}
else if (_elements.Length == _depth)
{
Element[] newElementNodes = new Element[_depth * 2];
Array.Copy(_elements, 0, newElementNodes, 0, _depth);
_elements = newElementNodes;
}
Element element = _elements[_depth];
if (element == null)
{
element = new Element();
_elements[_depth] = element;
}
return element;
}
private void ExitScope()
{
_elements[_depth].Clear();
_depth--;
if (_depth == 0 && _documentState == DocumentState.Document)
_documentState = DocumentState.Epilog;
_nsMgr.ExitScope();
}
protected void FlushElement()
{
if (_writeState == WriteState.Element)
{
AutoComplete(WriteState.Content);
}
}
private Task FlushElementAsync()
{
return _writeState == WriteState.Element ? AutoCompleteAsync(WriteState.Content) : Task.CompletedTask;
}
protected void StartComment()
{
FlushElement();
}
protected void EndComment()
{
}
protected void StartContent()
{
FlushElement();
if (_depth == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlIllegalOutsideRoot)));
}
protected async Task StartContentAsync()
{
await FlushElementAsync().ConfigureAwait(false);
if (_depth == 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlIllegalOutsideRoot)));
}
protected void StartContent(char ch)
{
FlushElement();
if (_depth == 0)
VerifyWhitespace(ch);
}
protected void StartContent(string s)
{
FlushElement();
if (_depth == 0)
VerifyWhitespace(s);
}
protected void StartContent(char[] chars, int offset, int count)
{
FlushElement();
if (_depth == 0)
VerifyWhitespace(chars, offset, count);
}
private void VerifyWhitespace(char ch)
{
if (!IsWhitespace(ch))
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlIllegalOutsideRoot)));
}
private void VerifyWhitespace(string s)
{
for (int i = 0; i < s.Length; i++)
if (!IsWhitespace(s[i]))
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlIllegalOutsideRoot)));
}
private void VerifyWhitespace(char[] chars, int offset, int count)
{
for (int i = 0; i < count; i++)
if (!IsWhitespace(chars[offset + i]))
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlIllegalOutsideRoot)));
}
private bool IsWhitespace(char ch)
{
return (ch == ' ' || ch == '\n' || ch == '\r' || ch == 't');
}
protected void EndContent()
{
}
private void AutoComplete(WriteState writeState)
{
if (_writeState == WriteState.Element)
{
EndStartElement();
}
_writeState = writeState;
}
private async Task AutoCompleteAsync(WriteState writeState)
{
if (_writeState == WriteState.Element)
{
await EndStartElementAsync().ConfigureAwait(false);
}
_writeState = writeState;
}
private void EndStartElement()
{
_nsMgr.DeclareNamespaces(_writer);
_writer.WriteEndStartElement(false);
}
private Task EndStartElementAsync()
{
_nsMgr.DeclareNamespaces(_writer);
return _writer.WriteEndStartElementAsync(false);
}
public override string LookupPrefix(string ns)
{
if (ns == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("ns"));
if (IsClosed)
ThrowClosed();
return _nsMgr.LookupPrefix(ns);
}
internal string LookupNamespace(string prefix)
{
if (prefix == null)
return null;
return _nsMgr.LookupNamespace(prefix);
}
private string GetQualifiedNamePrefix(string namespaceUri, XmlDictionaryString xNs)
{
string prefix = _nsMgr.LookupPrefix(namespaceUri);
if (prefix == null)
{
if (_writeState != WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlNamespaceNotFound, namespaceUri), "namespaceUri"));
prefix = GeneratePrefix(namespaceUri, xNs);
}
return prefix;
}
public override void WriteQualifiedName(string localName, string namespaceUri)
{
if (IsClosed)
ThrowClosed();
if (localName == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName"));
if (localName.Length == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.InvalidLocalNameEmpty), "localName"));
if (namespaceUri == null)
namespaceUri = string.Empty;
string prefix = GetQualifiedNamePrefix(namespaceUri, null);
if (prefix.Length != 0)
{
WriteString(prefix);
WriteString(":");
}
WriteString(localName);
}
public override void WriteQualifiedName(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
{
if (IsClosed)
ThrowClosed();
if (localName == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName"));
if (localName.Value.Length == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.InvalidLocalNameEmpty), "localName"));
if (namespaceUri == null)
namespaceUri = XmlDictionaryString.Empty;
string prefix = GetQualifiedNamePrefix(namespaceUri.Value, namespaceUri);
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(string.Concat(prefix, ":", namespaceUri.Value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteQualifiedName(prefix, localName);
EndContent();
}
}
public override void WriteStartDocument()
{
if (IsClosed)
ThrowClosed();
if (_writeState != WriteState.Start)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteStartDocument", WriteState.ToString())));
_writeState = WriteState.Prolog;
_documentState = DocumentState.Document;
_writer.WriteDeclaration();
}
public override void WriteStartDocument(bool standalone)
{
if (IsClosed)
ThrowClosed();
WriteStartDocument();
}
public override void WriteProcessingInstruction(string name, string text)
{
if (IsClosed)
ThrowClosed();
if (name != "xml")
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlProcessingInstructionNotSupported), "name"));
if (_writeState != WriteState.Start)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidDeclaration)));
// The only thing the text can legitimately contain is version, encoding, and standalone.
// We only support version 1.0, we can only write whatever encoding we were supplied,
// and we don't support DTDs, so whatever values are supplied in the text argument are irrelevant.
_writer.WriteDeclaration();
}
private void FinishDocument()
{
if (_writeState == WriteState.Attribute)
{
WriteEndAttribute();
}
while (_depth > 0)
{
WriteEndElement();
}
}
public override void WriteEndDocument()
{
if (IsClosed)
ThrowClosed();
if (_writeState == WriteState.Start || _writeState == WriteState.Prolog)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlNoRootElement)));
FinishDocument();
_writeState = WriteState.Start;
_documentState = DocumentState.End;
}
protected int NamespaceBoundary
{
get
{
return _nsMgr.NamespaceBoundary;
}
set
{
_nsMgr.NamespaceBoundary = value;
}
}
public override void WriteEntityRef(string name)
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(string.Format(SRSerialization.XmlMethodNotSupported, "WriteEntityRef")));
}
public override void WriteName(string name)
{
if (IsClosed)
ThrowClosed();
WriteString(name);
}
public override void WriteNmToken(string name)
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(string.Format(SRSerialization.XmlMethodNotSupported, "WriteNmToken")));
}
public override void WriteWhitespace(string whitespace)
{
if (IsClosed)
ThrowClosed();
if (whitespace == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("whitespace");
for (int i = 0; i < whitespace.Length; ++i)
{
char c = whitespace[i];
if (c != ' ' &&
c != '\t' &&
c != '\n' &&
c != '\r')
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlOnlyWhitespace), "whitespace"));
}
WriteString(whitespace);
}
public override void WriteString(string value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
value = string.Empty;
if (value.Length > 0 || _inList)
{
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(value);
if (!_isXmlnsAttribute)
{
StartContent(value);
_writer.WriteEscapedText(value);
EndContent();
}
}
}
public override void WriteString(XmlDictionaryString value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
if (value.Value.Length > 0)
{
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(value.Value);
if (!_isXmlnsAttribute)
{
StartContent(value.Value);
_writer.WriteEscapedText(value);
EndContent();
}
}
}
public override void WriteChars(char[] chars, int offset, int count)
{
if (IsClosed)
ThrowClosed();
if (chars == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
// Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does.
if (offset < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count > chars.Length - offset)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
if (count > 0)
{
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(new string(chars, offset, count));
if (!_isXmlnsAttribute)
{
StartContent(chars, offset, count);
_writer.WriteEscapedText(chars, offset, count);
EndContent();
}
}
}
public override void WriteRaw(string value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
value = string.Empty;
if (value.Length > 0)
{
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(value);
if (!_isXmlnsAttribute)
{
StartContent(value);
_writer.WriteText(value);
EndContent();
}
}
}
public override void WriteRaw(char[] chars, int offset, int count)
{
if (IsClosed)
ThrowClosed();
if (chars == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars"));
// Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does.
if (offset < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count > chars.Length - offset)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
if (count > 0)
{
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(new string(chars, offset, count));
if (!_isXmlnsAttribute)
{
StartContent(chars, offset, count);
_writer.WriteText(chars, offset, count);
EndContent();
}
}
}
public override void WriteCharEntity(char ch)
{
if (IsClosed)
ThrowClosed();
if (ch >= 0xd800 && ch <= 0xdfff)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlMissingLowSurrogate), "ch"));
if (_attributeValue != null)
WriteAttributeText(ch.ToString());
if (!_isXmlnsAttribute)
{
StartContent(ch);
FlushBase64();
_writer.WriteCharEntity(ch);
EndContent();
}
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
if (IsClosed)
ThrowClosed();
SurrogateChar ch = new SurrogateChar(lowChar, highChar);
if (_attributeValue != null)
{
char[] chars = new char[2] { highChar, lowChar };
WriteAttributeText(new string(chars));
}
if (!_isXmlnsAttribute)
{
StartContent();
FlushBase64();
_writer.WriteCharEntity(ch.Char);
EndContent();
}
}
public override void WriteValue(object value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
else if (value is object[])
{
WriteValue((object[])value);
}
else if (value is Array)
{
WriteValue((Array)value);
}
else
{
WritePrimitiveValue(value);
}
}
protected void WritePrimitiveValue(object value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
if (value is ulong)
{
WriteValue((ulong)value);
}
else if (value is string)
{
WriteValue((string)value);
}
else if (value is int)
{
WriteValue((int)value);
}
else if (value is long)
{
WriteValue((long)value);
}
else if (value is bool)
{
WriteValue((bool)value);
}
else if (value is double)
{
WriteValue((double)value);
}
else if (value is DateTime)
{
WriteValue((DateTime)value);
}
else if (value is float)
{
WriteValue((float)value);
}
else if (value is decimal)
{
WriteValue((decimal)value);
}
else if (value is XmlDictionaryString)
{
WriteValue((XmlDictionaryString)value);
}
else if (value is UniqueId)
{
WriteValue((UniqueId)value);
}
else if (value is Guid)
{
WriteValue((Guid)value);
}
else if (value is TimeSpan)
{
WriteValue((TimeSpan)value);
}
else if (value.GetType().IsArray)
{
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlNestedArraysNotSupported), "value"));
}
else
{
base.WriteValue(value);
}
}
public override void WriteValue(string value)
{
if (IsClosed)
ThrowClosed();
WriteString(value);
}
public override void WriteValue(int value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteInt32Text(value);
EndContent();
}
}
public override void WriteValue(long value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteInt64Text(value);
EndContent();
}
}
private void WriteValue(ulong value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteUInt64Text(value);
EndContent();
}
}
public override void WriteValue(bool value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteBoolText(value);
EndContent();
}
}
public override void WriteValue(decimal value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteDecimalText(value);
EndContent();
}
}
public override void WriteValue(float value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteFloatText(value);
EndContent();
}
}
public override void WriteValue(double value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteDoubleText(value);
EndContent();
}
}
public override void WriteValue(XmlDictionaryString value)
{
WriteString(value);
}
public override void WriteValue(DateTime value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteDateTimeText(value);
EndContent();
}
}
public override void WriteValue(UniqueId value)
{
if (IsClosed)
ThrowClosed();
if (value == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteUniqueIdText(value);
EndContent();
}
}
public override void WriteValue(Guid value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteGuidText(value);
EndContent();
}
}
public override void WriteValue(TimeSpan value)
{
if (IsClosed)
ThrowClosed();
FlushBase64();
if (_attributeValue != null)
WriteAttributeText(XmlConverter.ToString(value));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteTimeSpanText(value);
EndContent();
}
}
public override void WriteBase64(byte[] buffer, int offset, int count)
{
if (IsClosed)
ThrowClosed();
if (buffer == null)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
// Not checking upper bound because it will be caught by "count". This is what XmlTextWriter does.
if (offset < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count < 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.ValueMustBeNonNegative)));
if (count > buffer.Length - offset)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", string.Format(SRSerialization.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
if (count > 0)
{
if (_trailByteCount > 0)
{
while (_trailByteCount < 3 && count > 0)
{
_trailBytes[_trailByteCount++] = buffer[offset++];
count--;
}
}
int totalByteCount = _trailByteCount + count;
int actualByteCount = totalByteCount - (totalByteCount % 3);
if (_trailBytes == null)
{
_trailBytes = new byte[3];
}
if (actualByteCount >= 3)
{
if (_attributeValue != null)
{
WriteAttributeText(XmlConverter.Base64Encoding.GetString(_trailBytes, 0, _trailByteCount));
WriteAttributeText(XmlConverter.Base64Encoding.GetString(buffer, offset, actualByteCount - _trailByteCount));
}
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteBase64Text(_trailBytes, _trailByteCount, buffer, offset, actualByteCount - _trailByteCount);
EndContent();
}
_trailByteCount = (totalByteCount - actualByteCount);
if (_trailByteCount > 0)
{
int trailOffset = offset + count - _trailByteCount;
for (int i = 0; i < _trailByteCount; i++)
_trailBytes[i] = buffer[trailOffset++];
}
}
else
{
Buffer.BlockCopy(buffer, offset, _trailBytes, _trailByteCount, count);
_trailByteCount += count;
}
}
}
public override bool CanCanonicalize
{
get
{
return false;
}
}
public override void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
public override void EndCanonicalization()
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
private void FlushBase64()
{
if (_trailByteCount > 0)
{
FlushTrailBytes();
}
}
private Task FlushBase64Async()
{
return _trailByteCount > 0 ? FlushTrailBytesAsync() : Task.CompletedTask;
}
private void FlushTrailBytes()
{
if (_attributeValue != null)
WriteAttributeText(XmlConverter.Base64Encoding.GetString(_trailBytes, 0, _trailByteCount));
if (!_isXmlnsAttribute)
{
StartContent();
_writer.WriteBase64Text(_trailBytes, _trailByteCount, _trailBytes, 0, 0);
EndContent();
}
_trailByteCount = 0;
}
private async Task FlushTrailBytesAsync()
{
if (_attributeValue != null)
WriteAttributeText(XmlConverter.Base64Encoding.GetString(_trailBytes, 0, _trailByteCount));
if (!_isXmlnsAttribute)
{
await StartContentAsync().ConfigureAwait(false);
await _writer.WriteBase64TextAsync(_trailBytes, _trailByteCount, _trailBytes, 0, 0).ConfigureAwait(false);
EndContent();
}
_trailByteCount = 0;
}
private void WriteValue(object[] array)
{
FlushBase64();
StartContent();
_writer.WriteStartListText();
_inList = true;
for (int i = 0; i < array.Length; i++)
{
if (i != 0)
{
_writer.WriteListSeparator();
}
WritePrimitiveValue(array[i]);
}
_inList = false;
_writer.WriteEndListText();
EndContent();
}
private void WriteValue(Array array)
{
FlushBase64();
StartContent();
_writer.WriteStartListText();
_inList = true;
for (int i = 0; i < array.Length; i++)
{
if (i != 0)
{
_writer.WriteListSeparator();
}
WritePrimitiveValue(array.GetValue(i));
}
_inList = false;
_writer.WriteEndListText();
EndContent();
}
protected void StartArray(int count)
{
FlushBase64();
if (_documentState == DocumentState.Epilog)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlOnlyOneRoot)));
if (_documentState == DocumentState.Document && count > 1 && _depth == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlOnlyOneRoot)));
if (_writeState == WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidWriteState, "WriteStartElement", WriteState.ToString())));
AutoComplete(WriteState.Content);
}
protected void EndArray()
{
}
private string GeneratePrefix(string ns, XmlDictionaryString xNs)
{
if (_writeState != WriteState.Element && _writeState != WriteState.Attribute)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRSerialization.XmlInvalidPrefixState, WriteState.ToString())));
string prefix = _nsMgr.AddNamespace(ns, xNs);
if (prefix != null)
return prefix;
while (true)
{
int prefixId = _elements[_depth].PrefixId++;
prefix = string.Concat("d", _depth.ToString(CultureInfo.InvariantCulture), "p", prefixId.ToString(CultureInfo.InvariantCulture));
if (_nsMgr.LookupNamespace(prefix) == null)
{
_nsMgr.AddNamespace(prefix, ns, xNs);
return prefix;
}
}
}
private void WriteAttributeText(string value)
{
if (_attributeValue.Length == 0)
_attributeValue = value;
else
_attributeValue += value;
}
private class Element
{
private string _prefix;
private string _localName;
private int _prefixId;
public string Prefix
{
get
{
return _prefix;
}
set
{
_prefix = value;
}
}
public string LocalName
{
get
{
return _localName;
}
set
{
_localName = value;
}
}
public int PrefixId
{
get
{
return _prefixId;
}
set
{
_prefixId = value;
}
}
public void Clear()
{
_prefix = null;
_localName = null;
_prefixId = 0;
}
}
private enum DocumentState : byte
{
None, // Not inside StartDocument/EndDocument - Allows multiple root elemnts
Document, // Inside StartDocument/EndDocument
Epilog, // EndDocument must be called
End // Nothing further to write
}
private class NamespaceManager
{
private Namespace[] _namespaces;
private Namespace _lastNameSpace;
private int _nsCount;
private int _depth;
private XmlAttribute[] _attributes;
private int _attributeCount;
private XmlSpace _space;
private string _lang;
private int _namespaceBoundary;
private int _nsTop;
private Namespace _defaultNamespace;
public NamespaceManager()
{
_defaultNamespace = new Namespace();
_defaultNamespace.Depth = 0;
_defaultNamespace.Prefix = string.Empty;
_defaultNamespace.Uri = string.Empty;
_defaultNamespace.UriDictionaryString = null;
}
public string XmlLang
{
get
{
return _lang;
}
}
public XmlSpace XmlSpace
{
get
{
return _space;
}
}
public void Clear()
{
if (_namespaces == null)
{
_namespaces = new Namespace[4];
_namespaces[0] = _defaultNamespace;
}
_nsCount = 1;
_nsTop = 0;
_depth = 0;
_attributeCount = 0;
_space = XmlSpace.None;
_lang = null;
_lastNameSpace = null;
_namespaceBoundary = 0;
}
public int NamespaceBoundary
{
get
{
return _namespaceBoundary;
}
set
{
int i;
for (i = 0; i < _nsCount; i++)
if (_namespaces[i].Depth >= value)
break;
_nsTop = i;
_namespaceBoundary = value;
_lastNameSpace = null;
}
}
public void Close()
{
if (_depth == 0)
{
if (_namespaces != null && _namespaces.Length > 32)
_namespaces = null;
if (_attributes != null && _attributes.Length > 4)
_attributes = null;
}
else
{
_namespaces = null;
_attributes = null;
}
_lang = null;
}
public void DeclareNamespaces(XmlNodeWriter writer)
{
int i = _nsCount;
while (i > 0)
{
Namespace nameSpace = _namespaces[i - 1];
if (nameSpace.Depth != _depth)
break;
i--;
}
while (i < _nsCount)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.UriDictionaryString != null)
writer.WriteXmlnsAttribute(nameSpace.Prefix, nameSpace.UriDictionaryString);
else
writer.WriteXmlnsAttribute(nameSpace.Prefix, nameSpace.Uri);
i++;
}
}
public void EnterScope()
{
_depth++;
}
public void ExitScope()
{
while (_nsCount > 0)
{
Namespace nameSpace = _namespaces[_nsCount - 1];
if (nameSpace.Depth != _depth)
break;
if (_lastNameSpace == nameSpace)
_lastNameSpace = null;
nameSpace.Clear();
_nsCount--;
}
while (_attributeCount > 0)
{
XmlAttribute attribute = _attributes[_attributeCount - 1];
if (attribute.Depth != _depth)
break;
_space = attribute.XmlSpace;
_lang = attribute.XmlLang;
attribute.Clear();
_attributeCount--;
}
_depth--;
}
public void AddLangAttribute(string lang)
{
AddAttribute();
_lang = lang;
}
public void AddSpaceAttribute(XmlSpace space)
{
AddAttribute();
_space = space;
}
private void AddAttribute()
{
if (_attributes == null)
{
_attributes = new XmlAttribute[1];
}
else if (_attributes.Length == _attributeCount)
{
XmlAttribute[] newAttributes = new XmlAttribute[_attributeCount * 2];
Array.Copy(_attributes, 0, newAttributes, 0, _attributeCount);
_attributes = newAttributes;
}
XmlAttribute attribute = _attributes[_attributeCount];
if (attribute == null)
{
attribute = new XmlAttribute();
_attributes[_attributeCount] = attribute;
}
attribute.XmlLang = _lang;
attribute.XmlSpace = _space;
attribute.Depth = _depth;
_attributeCount++;
}
public string AddNamespace(string uri, XmlDictionaryString uriDictionaryString)
{
if (uri.Length == 0)
{
// Empty namespace can only be bound to the empty prefix
AddNamespaceIfNotDeclared(string.Empty, uri, uriDictionaryString);
return string.Empty;
}
else
{
for (int i = 0; i < s_prefixes.Length; i++)
{
string prefix = s_prefixes[i];
bool declared = false;
for (int j = _nsCount - 1; j >= _nsTop; j--)
{
Namespace nameSpace = _namespaces[j];
if (nameSpace.Prefix == prefix)
{
declared = true;
break;
}
}
if (!declared)
{
AddNamespace(prefix, uri, uriDictionaryString);
return prefix;
}
}
}
return null;
}
public void AddNamespaceIfNotDeclared(string prefix, string uri, XmlDictionaryString uriDictionaryString)
{
if (LookupNamespace(prefix) != uri)
{
AddNamespace(prefix, uri, uriDictionaryString);
}
}
public void AddNamespace(string prefix, string uri, XmlDictionaryString uriDictionaryString)
{
if (prefix.Length >= 3)
{
// Upper and lower case letter differ by a bit.
if ((prefix[0] & ~32) == 'X' && (prefix[1] & ~32) == 'M' && (prefix[2] & ~32) == 'L')
{
if (prefix == "xml" && uri == xmlNamespace)
return;
if (prefix == "xmlns" && uri == xmlnsNamespace)
return;
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlReservedPrefix), "prefix"));
}
}
Namespace nameSpace;
for (int i = _nsCount - 1; i >= 0; i--)
{
nameSpace = _namespaces[i];
if (nameSpace.Depth != _depth)
break;
if (nameSpace.Prefix == prefix)
{
if (nameSpace.Uri == uri)
return;
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlPrefixBoundToNamespace, prefix, nameSpace.Uri, uri), "prefix"));
}
}
if (prefix.Length != 0 && uri.Length == 0)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlEmptyNamespaceRequiresNullPrefix), "prefix"));
if (uri.Length == xmlnsNamespace.Length && uri == xmlnsNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlSpecificBindingNamespace, "xmlns", uri)));
// The addressing namespace and the xmlNamespace are the same length, so add a quick check to try to disambiguate
if (uri.Length == xmlNamespace.Length && uri[18] == 'X' && uri == xmlNamespace)
throw /*System.Runtime.Serialization.*/DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRSerialization.XmlSpecificBindingNamespace, "xml", uri)));
if (_namespaces.Length == _nsCount)
{
Namespace[] newNamespaces = new Namespace[_nsCount * 2];
Array.Copy(_namespaces, 0, newNamespaces, 0, _nsCount);
_namespaces = newNamespaces;
}
nameSpace = _namespaces[_nsCount];
if (nameSpace == null)
{
nameSpace = new Namespace();
_namespaces[_nsCount] = nameSpace;
}
nameSpace.Depth = _depth;
nameSpace.Prefix = prefix;
nameSpace.Uri = uri;
nameSpace.UriDictionaryString = uriDictionaryString;
_nsCount++;
_lastNameSpace = null;
}
public string LookupPrefix(string ns)
{
if (_lastNameSpace != null && _lastNameSpace.Uri == ns)
return _lastNameSpace.Prefix;
int nsCount = _nsCount;
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (object.ReferenceEquals(nameSpace.Uri, ns))
{
string prefix = nameSpace.Prefix;
// Make sure that the prefix refers to the namespace in scope
bool declared = false;
for (int j = i + 1; j < nsCount; j++)
{
if (_namespaces[j].Prefix == prefix)
{
declared = true;
break;
}
}
if (!declared)
{
_lastNameSpace = nameSpace;
return prefix;
}
}
}
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.Uri == ns)
{
string prefix = nameSpace.Prefix;
// Make sure that the prefix refers to the namespace in scope
bool declared = false;
for (int j = i + 1; j < nsCount; j++)
{
if (_namespaces[j].Prefix == prefix)
{
declared = true;
break;
}
}
if (!declared)
{
_lastNameSpace = nameSpace;
return prefix;
}
}
}
if (ns.Length == 0)
{
// Make sure the default binding is still valid
bool emptyPrefixUnassigned = true;
for (int i = nsCount - 1; i >= _nsTop; i--)
{
if (_namespaces[i].Prefix.Length == 0)
{
emptyPrefixUnassigned = false;
break;
}
}
if (emptyPrefixUnassigned)
return string.Empty;
}
if (ns == xmlnsNamespace)
return "xmlns";
if (ns == xmlNamespace)
return "xml";
return null;
}
public string LookupAttributePrefix(string ns)
{
if (_lastNameSpace != null && _lastNameSpace.Uri == ns && _lastNameSpace.Prefix.Length != 0)
return _lastNameSpace.Prefix;
int nsCount = _nsCount;
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (object.ReferenceEquals(nameSpace.Uri, ns))
{
string prefix = nameSpace.Prefix;
if (prefix.Length != 0)
{
// Make sure that the prefix refers to the namespace in scope
bool declared = false;
for (int j = i + 1; j < nsCount; j++)
{
if (_namespaces[j].Prefix == prefix)
{
declared = true;
break;
}
}
if (!declared)
{
_lastNameSpace = nameSpace;
return prefix;
}
}
}
}
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.Uri == ns)
{
string prefix = nameSpace.Prefix;
if (prefix.Length != 0)
{
// Make sure that the prefix refers to the namespace in scope
bool declared = false;
for (int j = i + 1; j < nsCount; j++)
{
if (_namespaces[j].Prefix == prefix)
{
declared = true;
break;
}
}
if (!declared)
{
_lastNameSpace = nameSpace;
return prefix;
}
}
}
}
if (ns.Length == 0)
return string.Empty;
return null;
}
public string LookupNamespace(string prefix)
{
int nsCount = _nsCount;
if (prefix.Length == 0)
{
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.Prefix.Length == 0)
return nameSpace.Uri;
}
return string.Empty;
}
if (prefix.Length == 1)
{
char prefixChar = prefix[0];
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.PrefixChar == prefixChar)
return nameSpace.Uri;
}
return null;
}
for (int i = nsCount - 1; i >= _nsTop; i--)
{
Namespace nameSpace = _namespaces[i];
if (nameSpace.Prefix == prefix)
return nameSpace.Uri;
}
if (prefix == "xmlns")
return xmlnsNamespace;
if (prefix == "xml")
return xmlNamespace;
return null;
}
private class XmlAttribute
{
private XmlSpace _space;
private string _lang;
private int _depth;
public XmlAttribute()
{
}
public int Depth
{
get
{
return _depth;
}
set
{
_depth = value;
}
}
public string XmlLang
{
get
{
return _lang;
}
set
{
_lang = value;
}
}
public XmlSpace XmlSpace
{
get
{
return _space;
}
set
{
_space = value;
}
}
public void Clear()
{
_lang = null;
}
}
private class Namespace
{
private string _prefix;
private string _ns;
private XmlDictionaryString _xNs;
private int _depth;
private char _prefixChar;
public Namespace()
{
}
public void Clear()
{
_prefix = null;
_prefixChar = (char)0;
_ns = null;
_xNs = null;
_depth = 0;
}
public int Depth
{
get
{
return _depth;
}
set
{
_depth = value;
}
}
public char PrefixChar
{
get
{
return _prefixChar;
}
}
public string Prefix
{
get
{
return _prefix;
}
set
{
if (value.Length == 1)
_prefixChar = value[0];
else
_prefixChar = (char)0;
_prefix = value;
}
}
public string Uri
{
get
{
return _ns;
}
set
{
_ns = value;
}
}
public XmlDictionaryString UriDictionaryString
{
get
{
return _xNs;
}
set
{
_xNs = value;
}
}
}
}
}
}
|