2 // System.Xml.Serialization.XmlSerializationReader.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Lluis Sanchez Gual (lluis@ximian.com)
\r
9 // Copyright (C) Tim Coleman, 2002
10 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
14 using System.Collections;
17 namespace System.Xml.Serialization {
18 public abstract class XmlSerializationReader {
26 Hashtable readCallbacks;
27 Hashtable typesCallbacks;
28 ArrayList noIDTargets;
30 XmlSerializer eventSource;
33 string w3SchemaNS2000;
34 string w3SchemaNS1999;
36 string w3InstanceNS2000;
37 string w3InstanceNS1999;
49 internal void Initialize (XmlReader reader, XmlSerializer eventSource)
51 w3SchemaNS = reader.NameTable.Add ("http://www.w3.org/2001/XMLSchema");
52 w3SchemaNS2000 = reader.NameTable.Add ("http://www.w3.org/2000/10/XMLSchema");
53 w3SchemaNS1999 = reader.NameTable.Add ("http://www.w3.org/1999/XMLSchema");
54 w3InstanceNS = reader.NameTable.Add ("http://www.w3.org/2001/XMLSchema-instance");
55 w3InstanceNS2000 = reader.NameTable.Add ("http://www.w3.org/2000/10/XMLSchema-instance");
56 w3InstanceNS1999 = reader.NameTable.Add ("http://www.w3.org/1999/XMLSchema-instance");
57 soapNS = reader.NameTable.Add ("http://schemas.xmlsoap.org/soap/encoding/");
58 schema = reader.NameTable.Add ("schema");
59 wsdlNS = reader.NameTable.Add ("http://schemas.xmlsoap.org/wsdl/");
60 wsdlArrayType = reader.NameTable.Add ("arrayType");
61 nullX = reader.NameTable.Add ("null");
62 nil = reader.NameTable.Add ("nil");
63 typeX = reader.NameTable.Add ("type");
64 arrayType = reader.NameTable.Add ("arrayType");
65 anyType = reader.NameTable.Add ("anyType");
67 this.eventSource = eventSource;
71 internal virtual object ReadObject ()
\r
73 throw new NotImplementedException ();
76 private ArrayList EnsureArrayList (ArrayList list)
79 list = new ArrayList ();
83 private Hashtable EnsureHashtable (Hashtable hash)
86 hash = new Hashtable ();
90 protected XmlSerializationReader ()
94 protected XmlDocument Document
98 document = new XmlDocument (reader.NameTable);
104 protected XmlReader Reader {
105 get { return reader; }
110 protected void AddFixup (CollectionFixup fixup)
112 collFixups = EnsureArrayList (collFixups);
113 collFixups.Add(fixup);
116 protected void AddFixup (Fixup fixup)
118 fixups = EnsureArrayList (fixups);
122 protected void AddReadCallback (string name, string ns, Type type, XmlSerializationReadCallback read)
124 XmlNameTable nt = reader.NameTable;
125 XmlQualifiedName xqn = new XmlQualifiedName (nt.Add (name), nt.Add (ns));
126 readCallbacks = EnsureHashtable (readCallbacks);
127 readCallbacks.Add (xqn, read);
128 typesCallbacks = EnsureHashtable (typesCallbacks);
129 typesCallbacks.Add (xqn, type);
132 protected void AddTarget (string id, object o)
135 targets = EnsureHashtable (targets);
136 if (targets [id] == null)
141 noIDTargets = EnsureArrayList (noIDTargets);
146 private string CurrentTag ()
148 switch (reader.NodeType) {
149 case XmlNodeType.None:
150 return String.Format ("<{0} xmlns='{1}'>", reader.LocalName,
151 reader.NamespaceURI);
152 case XmlNodeType.Attribute:
154 case XmlNodeType.Text:
156 case XmlNodeType.ProcessingInstruction:
158 case XmlNodeType.Entity:
160 case XmlNodeType.EndElement:
167 protected Exception CreateAbstractTypeException (string name, string ns)
169 string message = "Error at " + name + " " + ns + ":" + CurrentTag ();
170 return new InvalidOperationException (message);
173 protected Exception CreateInvalidCastException (Type type, object value)
175 string message = String.Format ("Cannot assign object of type {0} to an object of " +
176 "type {1}.", value.GetType (), type);
177 return new InvalidCastException (message);
180 protected Exception CreateReadOnlyCollectionException (string name)
182 string message = String.Format ("Could not serialize {0}. Default constructors are " +
183 "required for collections and enumerators.", name);
184 return new InvalidOperationException (message);
187 protected Exception CreateUnknownConstantException (string value, Type enumType)
189 string message = String.Format ("'{0}' is not a valid value for {1}.", value, enumType);
190 return new InvalidOperationException (message);
193 protected Exception CreateUnknownNodeException ()
195 string message = "Unknown xml node -> " + CurrentTag ();
196 return new InvalidOperationException (message);
199 protected Exception CreateUnknownTypeException (XmlQualifiedName type)
201 string message = "Unknown type " + type.Namespace + ":" + type.Name + " " + CurrentTag ();
202 return new InvalidOperationException (message);
205 protected Array EnsureArrayIndex (Array a, int index, Type elementType)
207 if (a != null && index < a.Length)
217 Array result = Array.CreateInstance (elementType, size);
219 Array.Copy (a, result, index);
224 [MonoTODO ("Implement")]
225 protected void FixupArrayRefs (object fixup)
227 throw new NotImplementedException ();
230 [MonoTODO ("Implement")]
231 protected int GetArrayLength (string name, string ns)
233 throw new NotImplementedException ();
236 protected bool GetNullAttr ()
238 string na = reader.GetAttribute (nullX, w3InstanceNS);
239 if (na == string.Empty) {
240 na = reader.GetAttribute (nil, w3InstanceNS);
241 if (na == string.Empty) {
242 na = reader.GetAttribute (nullX, w3InstanceNS2000);
243 if (na == string.Empty)
244 na = reader.GetAttribute (nullX, w3InstanceNS1999);
247 return (na != string.Empty);
250 [MonoTODO ("Implement")]
251 protected object GetTarget (string id)
253 throw new NotImplementedException ();
256 [MonoTODO ("Implement")]
257 protected XmlQualifiedName GetXsiType ()
259 string typeName = Reader.GetAttribute ("xsi:type");
260 if (typeName == string.Empty || typeName == null) return null;
261 int i = typeName.IndexOf (":");
262 if (i == -1) return new XmlQualifiedName (typeName, "");
265 string prefix = typeName.Substring(0,i);
266 string name = typeName.Substring (i+1);
267 return new XmlQualifiedName (name, Reader.LookupNamespace (prefix));
271 protected abstract void InitCallbacks ();
272 protected abstract void InitIDs ();
274 protected bool IsXmlnsAttribute (string name)
276 int length = name.Length;
281 return (name == "xmlns");
283 return name.StartsWith ("xmlns:");
286 [MonoTODO ("Implement")]
287 protected void ParseWsdlArrayType (XmlAttribute attr)
289 throw new NotImplementedException ();
292 protected XmlQualifiedName ReadElementQualifiedName ()
294 if (reader.IsEmptyElement) {
296 return ToXmlQualifiedName (String.Empty);
299 XmlQualifiedName xqn = ToXmlQualifiedName(reader.ReadString ());
300 reader.ReadEndElement ();
304 protected void ReadEndElement ()
306 while (reader.NodeType == XmlNodeType.Whitespace)
309 if (reader.NodeType != XmlNodeType.None) {
310 reader.ReadEndElement ();
316 protected bool ReadNull ()
321 if (reader.IsEmptyElement) {
326 reader.ReadStartElement();
327 while (reader.NodeType != XmlNodeType.EndElement)
334 protected XmlQualifiedName ReadNullableQualifiedName ()
339 return ReadElementQualifiedName ();
342 protected string ReadNullableString ()
347 return reader.ReadElementString ();
350 protected bool ReadReference (out string fixupReference)
352 string href = reader.GetAttribute ("href");
354 fixupReference = null;
359 throw new InvalidOperationException("href not found: " + href);
361 fixupReference = href.Substring (1);
362 if (!reader.IsEmptyElement) {
363 reader.ReadStartElement ();
371 protected object ReadReferencedElement ()
373 return ReadReferencedElement (null, null);
376 protected object ReadReferencedElement (string name, string ns)
379 return ReadReferencingElement (name, ns, false, out unused);
382 protected void ReadReferencedElements ()
386 reader.MoveToContent();
387 XmlNodeType nt = reader.NodeType;
388 while (nt != XmlNodeType.EndElement && nt != XmlNodeType.None) {
389 ReadReferencingElement (null, null, true, out unused);
390 reader.MoveToContent ();
391 nt = reader.NodeType;
395 [MonoTODO ("Implement")]
396 protected object ReadReferencingElement (out string fixupReference)
398 return ReadReferencingElement (null, null, false, out fixupReference);
401 protected object ReadReferencingElement (string name, string ns, out string fixupReference)
403 return ReadReferencingElement (name, ns, false, out fixupReference);
407 protected object ReadReferencingElement (string name,
409 bool elementCanBeType,
410 out string fixupReference)
412 throw new NotImplementedException ();
415 protected IXmlSerializable ReadSerializable (IXmlSerializable serializable)
417 serializable.ReadXml (reader);
421 protected string ReadString (string value)
423 if (value == null || value == String.Empty)
424 return reader.ReadString ();
426 return (value + reader.ReadString ());
429 protected object ReadTypedPrimitive (XmlQualifiedName type)
431 XmlQualifiedName qname = GetXsiType ();
432 TypeData typeData = TypeTranslator.GetPrimitiveTypeData (qname.Name);
433 if (typeData == null || typeData.SchemaType != SchemaTypes.Primitive) throw new InvalidOperationException ("Unknown type: " + qname.Name);
434 return XmlCustomFormatter.FromXmlString (typeData.Type, Reader.ReadElementString ());
437 protected XmlNode ReadXmlNode (bool wrapped)
439 XmlNode node = Document.ReadNode (reader);
441 return node.FirstChild;
446 [MonoTODO ("Implement")]
447 protected void Referenced (object o)
449 throw new NotImplementedException ();
452 protected Array ShrinkArray (Array a, int length, Type elementType, bool isNullable)
454 if (length == 0 && isNullable) return null;
455 if (a == null) return Array.CreateInstance (elementType, length);
456 if (a.Length == length) return a;
458 Array result = Array.CreateInstance (elementType, length);
459 Array.Copy (a, result, length);
463 protected byte[] ToByteArrayBase64 (bool isNull)
465 return Convert.FromBase64String (Reader.ReadString());
468 [MonoTODO ("Implement")]
469 protected static byte[] ToByteArrayBase64 (string value)
471 throw new NotImplementedException ();
474 [MonoTODO ("Implement")]
475 protected byte[] ToByteArrayHex (bool isNull)
477 throw new NotImplementedException ();
480 [MonoTODO ("Implement")]
481 protected static byte[] ToByteArrayHex (string value)
483 throw new NotImplementedException ();
486 protected static char ToChar (string value)
488 return XmlCustomFormatter.ToChar (value);
491 protected static DateTime ToDate (string value)
493 return XmlCustomFormatter.ToDate (value);
496 protected static DateTime ToDateTime (string value)
498 return XmlCustomFormatter.ToDateTime (value);
501 protected static long ToEnum (string value, Hashtable h, string typeName)
503 return XmlCustomFormatter.ToEnum (value, h, typeName, true);
506 protected static DateTime ToTime (string value)
508 return XmlCustomFormatter.ToTime (value);
511 protected static string ToXmlName (string value)
513 return XmlCustomFormatter.ToXmlName (value);
516 protected static string ToXmlNCName (string value)
518 return XmlCustomFormatter.ToXmlNCName (value);
521 protected static string ToXmlNmToken (string value)
523 return XmlCustomFormatter.ToXmlNmToken (value);
526 protected static string ToXmlNmTokens (string value)
528 return XmlCustomFormatter.ToXmlNmTokens (value);
531 protected XmlQualifiedName ToXmlQualifiedName (string value)
535 int lastColon = value.LastIndexOf (':');
536 string decodedValue = XmlConvert.DecodeName (value);
538 name = reader.NameTable.Add (decodedValue);
539 ns = reader.LookupNamespace (String.Empty);
541 string prefix = value.Substring (0, lastColon);
542 ns = reader.LookupNamespace (prefix);
544 throw new InvalidOperationException ("namespace " + prefix + "not defined");
546 name = reader.NameTable.Add (value.Substring (lastColon + 1));
549 return new XmlQualifiedName (name, ns);
552 protected void UnknownAttribute (object o, XmlAttribute attr)
554 // TODO: line numbers
555 eventSource.OnUnknownAttribute (new XmlAttributeEventArgs (attr,0,0,o));
558 protected void UnknownElement (object o, XmlElement elem)
560 // TODO: line numbers
561 eventSource.OnUnknownElement (new XmlElementEventArgs(elem,0,0,o));
564 protected void UnknownNode (object o)
566 // TODO: line numbers
567 eventSource.OnUnknownNode (new XmlNodeEventArgs(0, 0, Reader.LocalName, Reader.Name, Reader.NamespaceURI, Reader.NodeType, o, Reader.Value));
568 if (Reader.NodeType != XmlNodeType.Attribute)
571 if (Reader.ReadState == ReadState.EndOfFile)
572 throw new InvalidOperationException ("End of document found");
576 protected void UnreferencedObject (string id, object o)
578 eventSource.OnUnreferencedObject (new UnreferencedObjectEventArgs (o,id));
581 #endregion // Methods
583 protected class CollectionFixup {
587 XmlSerializationCollectionFixupCallback callback;
589 object collectionItems;
596 public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, object collectionItems)
598 this.callback = callback;
599 this.collection = collection;
600 this.collectionItems = collectionItems;
603 #endregion // Constructors
607 public XmlSerializationCollectionFixupCallback Callback {
608 get { return callback; }
611 public object Collection {
612 get { return collection; }
615 public object CollectionItems {
616 get { return collectionItems; }
619 #endregion // Properties
622 protected class Fixup {
628 XmlSerializationFixupCallback callback;
635 public Fixup (object o, XmlSerializationFixupCallback callback, int count)
637 this.callback = callback;
641 public Fixup (object o, XmlSerializationFixupCallback callback, string[] ids)
643 this.callback = callback;
646 #endregion // Constructors
650 public XmlSerializationFixupCallback Callback {
651 get { return callback; }
654 public string[] Ids {
658 public object Source {
659 get { return source; }
660 set { source = value; }
663 #endregion // Properties