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 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
|
//------------------------------------------------------------------------------
// <copyright file="XmlRawWriter.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
using System;
using System.IO;
using System.Diagnostics;
#if !SILVERLIGHT
using System.Xml.XPath;
#endif
using System.Xml.Schema;
using System.Collections;
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 {
//
// Fields
//
// base64 converter
protected XmlRawWriterBase64Encoder base64Encoder;
// namespace resolver
protected IXmlNamespaceResolver resolver;
//
// XmlWriter implementation
//
// Raw writers do not have to track whether this is a well-formed document.
public override void WriteStartDocument() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override void WriteStartDocument(bool standalone) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override void WriteEndDocument() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT // This code is not being hit in Silverlight
public override void WriteDocType(string name, string pubid, string sysid, string subset) {
}
#endif
// Raw writers do not have to keep a stack of element names.
public override void WriteEndElement() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to keep a stack of element names.
public override void WriteFullEndElement() {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// By default, convert base64 value to string and call WriteString.
public override void WriteBase64( byte[] buffer, int index, int count ) {
if ( base64Encoder == null ) {
base64Encoder = new XmlRawWriterBase64Encoder( this );
}
// Encode will call WriteRaw to write out the encoded characters
base64Encoder.Encode( buffer, index, count );
}
// Raw writers do not have to keep track of namespaces.
public override string LookupPrefix( string ns ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to keep track of write states.
public override WriteState WriteState {
get {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
}
// Raw writers do not have to keep track of xml:space.
public override XmlSpace XmlSpace {
get { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); }
}
// Raw writers do not have to keep track of xml:lang.
public override string XmlLang {
get { throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); }
}
// Raw writers do not have to verify NmToken values.
public override void WriteNmToken( string name ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to verify Name values.
public override void WriteName( string name ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
// Raw writers do not have to verify QName values.
public override void WriteQualifiedName( string localName, string ns ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT // This code is not being hit in Silverlight
// Forward call to WriteString(string).
public override void WriteCData( string text ) {
WriteString( text );
}
// Forward call to WriteString(string).
public override void WriteCharEntity( char ch ) {
WriteString( new string( new char[] {ch} ) );
}
// Forward call to WriteString(string).
public override void WriteSurrogateCharEntity( char lowChar, char highChar ) {
WriteString( new string( new char[] {lowChar, highChar} ) );
}
// Forward call to WriteString(string).
public override void WriteWhitespace( string ws ) {
WriteString( ws );
}
// Forward call to WriteString(string).
public override void WriteChars( char[] buffer, int index, int count ) {
WriteString( new string( buffer, index, count ) );
}
// Forward call to WriteString(string).
public override void WriteRaw(char[] buffer, int index, int count) {
WriteString( new string( buffer, index, count ) );
}
// Forward call to WriteString(string).
public override void WriteRaw(string data) {
WriteString( data );
}
#endif
// Override in order to handle Xml simple typed values and to pass resolver for QName values
public override void WriteValue(object value) {
if ( value == null ) {
throw new ArgumentNullException( "value" );
}
#if SILVERLIGHT //
WriteString(XmlUntypedStringConverter.Instance.ToString( value, resolver ) );
#else
WriteString(XmlUntypedConverter.Untyped.ToString( value, resolver ) );
#endif
}
// Override in order to handle Xml simple typed values and to pass resolver for QName values
public override void WriteValue( string value ) {
WriteString( value );
}
public override void WriteValue(DateTimeOffset value) {
// For compatibility with custom writers, XmlWriter writes DateTimeOffset as DateTime.
// Our internal writers should use the DateTimeOffset-String conversion from XmlConvert.
WriteString(XmlConvert.ToString(value));
}
// Copying to XmlRawWriter is not currently supported.
public override void WriteAttributes( XmlReader reader, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
public override void WriteNode( XmlReader reader, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#if !SILVERLIGHT // Removing dependency on XPathNavigator
public override void WriteNode( System.Xml.XPath.XPathNavigator navigator, bool defattr ) {
throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
}
#endif
//
// XmlRawWriter methods and properties
//
// Get and set the namespace resolver that's used by this RawWriter to resolve prefixes.
internal virtual IXmlNamespaceResolver NamespaceResolver {
get {
return resolver;
}
set {
resolver = value;
}
}
// Write the xml declaration. This must be the first call.
#if !SILVERLIGHT // This code is not being hit in Silverlight
internal virtual void WriteXmlDeclaration( XmlStandalone standalone ) {
}
internal virtual void WriteXmlDeclaration( string xmldecl ) {
}
#else
internal abstract void WriteXmlDeclaration(XmlStandalone standalone);
internal abstract void WriteXmlDeclaration(string xmldecl);
#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 abstract void StartElementContent();
// Called before a root element is written (before the WriteStartElement call)
// the conformanceLevel specifies the current conformance level the writer is operating with.
internal virtual void OnRootElement(ConformanceLevel conformanceLevel) { }
// 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 abstract void WriteEndElement( string prefix, string localName, string ns );
#if !SILVERLIGHT // This code is not being hit in Silverlight
internal virtual void WriteFullEndElement( string prefix, string localName, string ns ) {
WriteEndElement( prefix, localName, ns );
}
#else
internal abstract void WriteFullEndElement(string prefix, string localName, string ns);
#endif
internal virtual void WriteQualifiedName( string prefix, string localName, string ns ) {
if ( prefix.Length != 0 ) {
WriteString( prefix );
WriteString( ":" );
}
WriteString( localName );
}
// This method must be called instead of WriteStartAttribute() for namespaces.
internal abstract void WriteNamespaceDeclaration( string prefix, string ns );
// When true, the XmlWellFormedWriter will call:
// 1) WriteStartNamespaceDeclaration
// 2) any method that can be used to write out a value of an attribute: WriteString, WriteChars, WriteRaw, WriteCharEntity...
// 3) 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 and entities.
internal virtual bool SupportsNamespaceDeclarationInChunks {
get {
return false;
}
}
internal virtual void WriteStartNamespaceDeclaration(string prefix) {
throw new NotSupportedException();
}
internal virtual void WriteEndNamespaceDeclaration() {
throw new NotSupportedException();
}
// This is called when the remainder of a base64 value should be output.
internal virtual void WriteEndBase64() {
// The Flush will call WriteRaw to write out the rest of the encoded characters
base64Encoder.Flush();
}
internal virtual void Close( WriteState currentState ) {
Close();
}
}
}
|