1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
using System;
using System.IO;
using System.Diagnostics;
#if !SILVERLIGHT
using System.Xml.XPath;
#endif
using System.Xml.Schema;
using System.Collections;
using System.Threading.Tasks;
namespace System.Xml {
/// <summary>
/// Implementations of XmlRawWriter are intended to be wrapped by the XmlWellFormedWriter. The
/// well-formed writer performs many checks in behalf of the raw writer, and keeps state that the
/// raw writer otherwise would have to keep. Therefore, the well-formed writer will call the
/// XmlRawWriter using the following rules, in order to make raw writers easier to implement:
///
/// 1. The well-formed writer keeps a stack of element names, and always calls
/// WriteEndElement(string, string, string) instead of WriteEndElement().
/// 2. The well-formed writer tracks namespaces, and will pass himself in via the
/// WellformedWriter property. It is used in the XmlRawWriter's implementation of IXmlNamespaceResolver.
/// Thus, LookupPrefix does not have to be implemented.
/// 3. The well-formed writer tracks write states, so the raw writer doesn't need to.
/// 4. The well-formed writer will always call StartElementContent.
/// 5. The well-formed writer will always call WriteNamespaceDeclaration for namespace nodes,
/// rather than calling WriteStartAttribute(). If the writer is supporting namespace declarations in chunks
/// (SupportsNamespaceDeclarationInChunks is true), the XmlWellFormedWriter will call WriteStartNamespaceDeclaration,
/// then any method that can be used to write out a value of an attribute (WriteString, WriteChars, WriteRaw, WriteCharEntity...)
/// and then WriteEndNamespaceDeclaration - instead of just a single WriteNamespaceDeclaration call. This feature will be
/// supported by raw writers serializing to text that wish to preserve the attribute value escaping etc.
/// 6. The well-formed writer guarantees a well-formed document, including correct call sequences,
/// correct namespaces, and correct document rule enforcement.
/// 7. All element and attribute names will be fully resolved and validated. Null will never be
/// passed for any of the name parts.
/// 8. The well-formed writer keeps track of xml:space and xml:lang.
/// 9. The well-formed writer verifies NmToken, Name, and QName values and calls WriteString().
/// </summary>
internal abstract partial class XmlRawWriter : XmlWriter {
//
// XmlWriter implementation
//
// Raw writers do not have to track whether this is a well-formed document.
public override Task WriteStartDocumentAsync() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override Task WriteStartDocumentAsync(bool standalone) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override Task WriteEndDocumentAsync() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT || ASYNC // This code is not being hit in Silverlight, but is used on CoreSys builds.
public override Task WriteDocTypeAsync(string name, string pubid, string sysid, string subset) {
return AsyncHelper.DoneTask;
}
#endif
// Raw writers do not have to keep a stack of element names.
public override Task WriteEndElementAsync() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to keep a stack of element names.
public override Task WriteFullEndElementAsync() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// By default, convert base64 value to string and call WriteString.
public override Task WriteBase64Async( byte[] buffer, int index, int count ) {
if ( base64Encoder == null ) {
base64Encoder = new XmlRawWriterBase64Encoder( this );
}
// Encode will call WriteRaw to write out the encoded characters
return base64Encoder.EncodeAsync( buffer, index, count );
}
// Raw writers do not have to verify NmToken values.
public override Task WriteNmTokenAsync( string name ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to verify Name values.
public override Task WriteNameAsync( string name ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to verify QName values.
public override Task WriteQualifiedNameAsync( string localName, string ns ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT || ASYNC // This code is not being hit in Silverlight, but is used on CoreSys
// Forward call to WriteString(string).
public override Task WriteCDataAsync( string text ) {
return WriteStringAsync( text );
}
// Forward call to WriteString(string).
public override Task WriteCharEntityAsync( char ch ) {
return WriteStringAsync( new string( new char[] {ch} ) );
}
// Forward call to WriteString(string).
public override Task WriteSurrogateCharEntityAsync( char lowChar, char highChar ) {
return WriteStringAsync( new string( new char[] {lowChar, highChar} ) );
}
// Forward call to WriteString(string).
public override Task WriteWhitespaceAsync( string ws ) {
return WriteStringAsync( ws );
}
// Forward call to WriteString(string).
public override Task WriteCharsAsync( char[] buffer, int index, int count ) {
return WriteStringAsync( new string( buffer, index, count ) );
}
// Forward call to WriteString(string).
public override Task WriteRawAsync(char[] buffer, int index, int count) {
return WriteStringAsync( new string( buffer, index, count ) );
}
// Forward call to WriteString(string).
public override Task WriteRawAsync(string data) {
return WriteStringAsync( data );
}
#endif
// Copying to XmlRawWriter is not currently supported.
public override Task WriteAttributesAsync( XmlReader reader, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override Task WriteNodeAsync( XmlReader reader, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT // Removing dependency on XPathNavigator
public override Task WriteNodeAsync( System.Xml.XPath.XPathNavigator navigator, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#endif
//
// XmlRawWriter methods and properties
//
// Write the xml declaration. This must be the first call.
#if !SILVERLIGHT || ASYNC // This code is not being hit in Silverlight, but is used on desktop and in CoreSys builds.
internal virtual Task WriteXmlDeclarationAsync( XmlStandalone standalone ) {
return AsyncHelper.DoneTask;
}
internal virtual Task WriteXmlDeclarationAsync( string xmldecl ) {
return AsyncHelper.DoneTask;
}
#else
internal virtual Task WriteXmlDeclarationAsync(XmlStandalone standalone) {
throw new NotImplementedException();
}
internal virtual Task WriteXmlDeclarationAsync(string xmldecl) {
throw new NotImplementedException();
}
#endif
// Called after an element's attributes have been enumerated, but before any children have been
// enumerated. This method must always be called, even for empty elements.
internal virtual Task StartElementContentAsync() {
throw new NotImplementedException();
}
// WriteEndElement() and WriteFullEndElement() overloads, in which caller gives the full name of the
// element, so that raw writers do not need to keep a stack of element names. This method should
// always be called instead of WriteEndElement() or WriteFullEndElement() without parameters.
internal virtual Task WriteEndElementAsync( string prefix, string localName, string ns ) {
throw new NotImplementedException();
}
#if !SILVERLIGHT || ASYNC // This code is not being hit in Silverlight, but is used on CoreSys builds.
internal virtual Task WriteFullEndElementAsync( string prefix, string localName, string ns ) {
return WriteEndElementAsync( prefix, localName, ns );
}
#else
internal virtual Task WriteFullEndElementAsync(string prefix, string localName, string ns) {
throw new NotImplementedException();
}
#endif
internal virtual async Task WriteQualifiedNameAsync( string prefix, string localName, string ns ) {
if ( prefix.Length != 0 ) {
await WriteStringAsync( prefix ).ConfigureAwait(false);
await WriteStringAsync( ":" ).ConfigureAwait(false);
}
await WriteStringAsync( localName ).ConfigureAwait(false);
}
// This method must be called instead of WriteStartAttribute() for namespaces.
internal virtual Task WriteNamespaceDeclarationAsync( string prefix, string ns ) {
throw new NotImplementedException();
}
internal virtual Task WriteStartNamespaceDeclarationAsync(string prefix) {
throw new NotSupportedException();
}
internal virtual Task WriteEndNamespaceDeclarationAsync() {
throw new NotSupportedException();
}
// This is called when the remainder of a base64 value should be output.
internal virtual Task WriteEndBase64Async() {
// The Flush will call WriteRaw to write out the rest of the encoded characters
return base64Encoder.FlushAsync();
}
}
}
|