XmlSerializationWriter.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. //
  2. // System.Xml.Serialization.XmlSerializationWriter.cs
  3. //
  4. // Author:
  5. // Tim Coleman ([email protected])
  6. // Lluis Sanchez Gual ([email protected])
  7. //
  8. // Copyright (C) Tim Coleman, 2002
  9. //
  10. using System;
  11. using System.Collections;
  12. using System.Text;
  13. using System.Xml;
  14. using System.Xml.Schema;
  15. using System.Runtime.Serialization;
  16. namespace System.Xml.Serialization {
  17. public abstract class XmlSerializationWriter {
  18. #region Fields
  19. ObjectIDGenerator idGenerator;
  20. int qnameCount;
  21. bool topLevelElement = false;
  22. ArrayList namespaces;
  23. XmlWriter writer;
  24. Queue referencedElements;
  25. Hashtable callbacks;
  26. Hashtable serializedObjects;
  27. const string xmlNamespace = "http://www.w3.org/2000/xmlns/";
  28. #endregion // Fields
  29. #region Constructors
  30. protected XmlSerializationWriter ()
  31. {
  32. qnameCount = 0;
  33. serializedObjects = new Hashtable ();
  34. }
  35. internal void Initialize (XmlWriter writer, XmlSerializerNamespaces nss)
  36. {
  37. this.writer = writer;
  38. if (nss != null)
  39. {
  40. namespaces = new ArrayList ();
  41. foreach (XmlQualifiedName ns in nss.ToArray())
  42. namespaces.Add (ns);
  43. }
  44. }
  45. #endregion // Constructors
  46. #region Properties
  47. protected ArrayList Namespaces {
  48. get { return namespaces; }
  49. set { namespaces = value; }
  50. }
  51. protected XmlWriter Writer {
  52. get { return writer; }
  53. set { writer = value; }
  54. }
  55. #endregion // Properties
  56. #region Methods
  57. protected void AddWriteCallback (Type type, string typeName, string typeNs, XmlSerializationWriteCallback callback)
  58. {
  59. WriteCallbackInfo info = new WriteCallbackInfo ();
  60. info.Type = type;
  61. info.TypeName = typeName;
  62. info.TypeNs = typeNs;
  63. info.Callback = callback;
  64. if (callbacks == null) callbacks = new Hashtable ();
  65. callbacks.Add (type, info);
  66. }
  67. protected Exception CreateMismatchChoiceException (string value, string elementName, string enumValue)
  68. {
  69. string message = String.Format ("Value of {0} mismatches the type of {1}, you need to set it to {2}.", elementName, value, enumValue);
  70. return new InvalidOperationException (message);
  71. }
  72. protected Exception CreateUnknownAnyElementException (string name, string ns)
  73. {
  74. string message = String.Format ("The XML element named '{0}' from namespace '{1}' was not expected. The XML element name and namespace must match those provided via XmlAnyElementAttribute(s).", name, ns);
  75. return new InvalidOperationException (message);
  76. }
  77. protected Exception CreateUnknownTypeException (object o)
  78. {
  79. return CreateUnknownTypeException (o.GetType ());
  80. }
  81. protected Exception CreateUnknownTypeException (Type type)
  82. {
  83. string message = String.Format ("The type {0} may not be used in this context.", type);
  84. return new InvalidOperationException (message);
  85. }
  86. protected static string FromByteArrayBase64 (byte[] value)
  87. {
  88. return XmlCustomFormatter.FromByteArrayBase64 (value);
  89. }
  90. protected static string FromByteArrayHex (byte[] value)
  91. {
  92. return XmlCustomFormatter.FromByteArrayHex (value);
  93. }
  94. protected static string FromChar (char value)
  95. {
  96. return XmlCustomFormatter.FromChar (value);
  97. }
  98. protected static string FromDate (DateTime value)
  99. {
  100. return XmlCustomFormatter.FromDate (value);
  101. }
  102. protected static string FromDateTime (DateTime value)
  103. {
  104. return XmlCustomFormatter.FromDateTime (value);
  105. }
  106. protected static string FromEnum (long value, string[] values, long[] ids)
  107. {
  108. return XmlCustomFormatter.FromEnum (value, values, ids);
  109. }
  110. protected static string FromTime (DateTime value)
  111. {
  112. return XmlCustomFormatter.FromTime (value);
  113. }
  114. protected static string FromXmlName (string name)
  115. {
  116. return XmlCustomFormatter.FromXmlName (name);
  117. }
  118. protected static string FromXmlNCName (string ncName)
  119. {
  120. return XmlCustomFormatter.FromXmlNCName (ncName);
  121. }
  122. protected static string FromXmlNmToken (string nmToken)
  123. {
  124. return XmlCustomFormatter.FromXmlNmToken (nmToken);
  125. }
  126. protected static string FromXmlNmTokens (string nmTokens)
  127. {
  128. return XmlCustomFormatter.FromXmlNmTokens (nmTokens);
  129. }
  130. protected string FromXmlQualifiedName (XmlQualifiedName xmlQualifiedName)
  131. {
  132. if (xmlQualifiedName == null || xmlQualifiedName == XmlQualifiedName.Empty)
  133. return null;
  134. return GetQualifiedName (xmlQualifiedName.Name, xmlQualifiedName.Namespace);
  135. }
  136. private string GetId (object o, bool addToReferencesList)
  137. {
  138. if (idGenerator == null) idGenerator = new ObjectIDGenerator ();
  139. bool firstTime;
  140. long lid = idGenerator.GetId (o, out firstTime);
  141. return String.Format ("id{0}", lid);
  142. }
  143. bool AlreadyQueued (object ob)
  144. {
  145. if (idGenerator == null) return false;
  146. bool firstTime;
  147. idGenerator.HasId (ob, out firstTime);
  148. return !firstTime;
  149. }
  150. private string GetNamespacePrefix (string ns)
  151. {
  152. string prefix = Writer.LookupPrefix (ns);
  153. if (prefix == null)
  154. {
  155. prefix = String.Format ("q{0}", ++qnameCount);
  156. WriteAttribute ("xmlns", prefix, null, ns);
  157. }
  158. return prefix;
  159. }
  160. [MonoTODO ("Need to check for namespace conflicts before blindly allocating qN")]
  161. private string GetQualifiedName (string name, string ns)
  162. {
  163. string prefix = GetNamespacePrefix (ns);
  164. if (prefix == String.Empty)
  165. return name;
  166. else
  167. return String.Format ("{0}:{1}", prefix, name);
  168. }
  169. protected abstract void InitCallbacks ();
  170. protected void TopLevelElement ()
  171. {
  172. topLevelElement = true;
  173. }
  174. protected void WriteAttribute (string localName, byte[] value)
  175. {
  176. WriteAttribute (localName, String.Empty, value);
  177. }
  178. protected void WriteAttribute (string localName, string value)
  179. {
  180. WriteAttribute (String.Empty, localName, String.Empty, value);
  181. }
  182. protected void WriteAttribute (string localName, string ns, byte[] value)
  183. {
  184. if (value == null)
  185. return;
  186. Writer.WriteStartAttribute (localName, ns);
  187. WriteValue (value);
  188. Writer.WriteEndAttribute ();
  189. }
  190. protected void WriteAttribute (string localName, string ns, string value)
  191. {
  192. WriteAttribute (null, localName, ns, value);
  193. }
  194. protected void WriteAttribute (string prefix, string localName, string ns, string value)
  195. {
  196. if (value == null)
  197. return;
  198. Writer.WriteAttributeString (prefix, localName, ns, value);
  199. }
  200. protected void WriteElementEncoded (XmlNode node, string name, string ns, bool isNullable, bool any)
  201. {
  202. if (name != string.Empty)
  203. {
  204. if (node == null)
  205. {
  206. if (isNullable)
  207. WriteNullTagEncoded (name, ns);
  208. }
  209. else
  210. {
  211. Writer.WriteStartElement (name, ns);
  212. node.WriteTo (Writer);
  213. Writer.WriteEndElement ();
  214. }
  215. }
  216. else
  217. node.WriteTo (Writer);
  218. }
  219. protected void WriteElementLiteral (XmlNode node, string name, string ns, bool isNullable, bool any)
  220. {
  221. if (name != string.Empty)
  222. {
  223. if (node == null)
  224. {
  225. if (isNullable)
  226. WriteNullTagLiteral (name, ns);
  227. }
  228. else
  229. {
  230. Writer.WriteStartElement (name, ns);
  231. node.WriteTo (Writer);
  232. Writer.WriteEndElement ();
  233. }
  234. }
  235. else
  236. node.WriteTo (Writer);
  237. }
  238. protected void WriteElementQualifiedName (string localName, XmlQualifiedName value)
  239. {
  240. WriteElementQualifiedName (localName, String.Empty, value, null);
  241. }
  242. protected void WriteElementQualifiedName (string localName, string ns, XmlQualifiedName value)
  243. {
  244. WriteElementQualifiedName (localName, ns, value, null);
  245. }
  246. protected void WriteElementQualifiedName (string localName, XmlQualifiedName value, XmlQualifiedName xsiType)
  247. {
  248. WriteElementQualifiedName (localName, String.Empty, value, xsiType);
  249. }
  250. protected void WriteElementQualifiedName (string localName, string ns, XmlQualifiedName value, XmlQualifiedName xsiType)
  251. {
  252. localName = XmlCustomFormatter.FromXmlNCName (localName);
  253. WriteStartElement (localName, ns);
  254. if (xsiType != null) WriteXsiType (xsiType.Name, xsiType.Namespace);
  255. Writer.WriteString (FromXmlQualifiedName (value));
  256. WriteEndElement ();
  257. }
  258. protected void WriteElementString (string localName, string value)
  259. {
  260. WriteElementString (localName, String.Empty, value, null);
  261. }
  262. protected void WriteElementString (string localName, string ns, string value)
  263. {
  264. WriteElementString (localName, ns, value, null);
  265. }
  266. protected void WriteElementString (string localName, string value, XmlQualifiedName xsiType)
  267. {
  268. WriteElementString (localName, String.Empty, value, xsiType);
  269. }
  270. [MonoTODO ("Implement")]
  271. protected void WriteElementString (string localName, string ns, string value, XmlQualifiedName xsiType)
  272. {
  273. if (value == null) return;
  274. if (xsiType != null) {
  275. localName = XmlCustomFormatter.FromXmlNCName (localName);
  276. WriteStartElement (localName, ns);
  277. WriteXsiType (xsiType.Name, xsiType.Namespace);
  278. Writer.WriteString (value);
  279. WriteEndElement ();
  280. }
  281. else
  282. Writer.WriteElementString (localName, ns, value);
  283. }
  284. protected void WriteElementStringRaw (string localName, byte[] value)
  285. {
  286. WriteElementStringRaw (localName, String.Empty, value, null);
  287. }
  288. protected void WriteElementStringRaw (string localName, string value)
  289. {
  290. WriteElementStringRaw (localName, String.Empty, value, null);
  291. }
  292. protected void WriteElementStringRaw (string localName, byte[] value, XmlQualifiedName xsiType)
  293. {
  294. WriteElementStringRaw (localName, String.Empty, value, xsiType);
  295. }
  296. protected void WriteElementStringRaw (string localName, string ns, byte[] value)
  297. {
  298. WriteElementStringRaw (localName, ns, value, null);
  299. }
  300. protected void WriteElementStringRaw (string localName, string ns, string value)
  301. {
  302. WriteElementStringRaw (localName, ns, value, null);
  303. }
  304. protected void WriteElementStringRaw (string localName, string value, XmlQualifiedName xsiType)
  305. {
  306. WriteElementStringRaw (localName, String.Empty, value, null);
  307. }
  308. [MonoTODO ("Implement")]
  309. protected void WriteElementStringRaw (string localName, string ns, byte[] value, XmlQualifiedName xsiType)
  310. {
  311. throw new NotImplementedException ();
  312. }
  313. [MonoTODO ("Implement")]
  314. protected void WriteElementStringRaw (string localName, string ns, string value, XmlQualifiedName xsiType)
  315. {
  316. localName = XmlCustomFormatter.FromXmlNCName (localName);
  317. WriteStartElement (localName, ns);
  318. if (xsiType != null)
  319. WriteXsiType (xsiType.Name, xsiType.Namespace);
  320. Writer.WriteRaw (value);
  321. WriteEndElement ();
  322. }
  323. protected void WriteEmptyTag (string name)
  324. {
  325. WriteEmptyTag (name, String.Empty);
  326. }
  327. [MonoTODO ("Verify")]
  328. protected void WriteEmptyTag (string name, string ns)
  329. {
  330. name = XmlCustomFormatter.FromXmlName (name);
  331. WriteStartElement (name, ns);
  332. WriteEndElement ();
  333. }
  334. protected void WriteEndElement ()
  335. {
  336. WriteEndElement (null);
  337. }
  338. protected void WriteEndElement (object o)
  339. {
  340. if (o != null)
  341. serializedObjects.Remove (o);
  342. Writer.WriteEndElement ();
  343. }
  344. protected void WriteId (object o)
  345. {
  346. WriteAttribute ("id", GetId (o, true));
  347. }
  348. protected void WriteNamespaceDeclarations (XmlSerializerNamespaces ns)
  349. {
  350. if (ns == null)
  351. return;
  352. ICollection namespaces = ns.Namespaces.Values;
  353. foreach (XmlQualifiedName qn in namespaces) {
  354. if (Writer.LookupPrefix (qn.Namespace) == null)
  355. WriteAttribute ("xmlns", qn.Name, xmlNamespace, qn.Namespace);
  356. }
  357. }
  358. protected void WriteNullableQualifiedNameEncoded (string name, string ns, XmlQualifiedName value, XmlQualifiedName xsiType)
  359. {
  360. if (value != null)
  361. WriteElementQualifiedName (name, ns, value, xsiType);
  362. else
  363. WriteNullTagEncoded (name, ns);
  364. }
  365. protected void WriteNullableQualifiedNameLiteral (string name, string ns, XmlQualifiedName value)
  366. {
  367. if (value != null)
  368. WriteElementQualifiedName (name, ns, value);
  369. else
  370. WriteNullTagLiteral (name, ns);
  371. }
  372. protected void WriteNullableStringEncoded (string name, string ns, string value, XmlQualifiedName xsiType)
  373. {
  374. if (value != null)
  375. WriteElementString (name, ns, value, xsiType);
  376. else
  377. WriteNullTagEncoded (name, ns);
  378. }
  379. [MonoTODO ("Implement")]
  380. protected void WriteNullableStringEncodedRaw (string name, string ns, byte[] value, XmlQualifiedName xsiType)
  381. {
  382. throw new NotImplementedException ();
  383. }
  384. [MonoTODO ("Implement")]
  385. protected void WriteNullableStringEncodedRaw (string name, string ns, string value, XmlQualifiedName xsiType)
  386. {
  387. throw new NotImplementedException ();
  388. }
  389. protected void WriteNullableStringLiteral (string name, string ns, string value)
  390. {
  391. if (value != null)
  392. WriteElementString (name, ns, value, null);
  393. else
  394. WriteNullTagLiteral (name, ns);
  395. }
  396. [MonoTODO ("Implement")]
  397. protected void WriteNullableStringLiteralRaw (string name, string ns, byte[] value)
  398. {
  399. throw new NotImplementedException ();
  400. }
  401. [MonoTODO ("Implement")]
  402. protected void WriteNullableStringLiteralRaw (string name, string ns, string value)
  403. {
  404. throw new NotImplementedException ();
  405. }
  406. protected void WriteNullTagEncoded (string name)
  407. {
  408. WriteNullTagEncoded (name, String.Empty);
  409. }
  410. protected void WriteNullTagEncoded (string name, string ns)
  411. {
  412. WriteStartElement (name, ns);
  413. WriteAttribute ("xsi","null", XmlSchema.InstanceNamespace, "1");
  414. WriteEndElement ();
  415. }
  416. protected void WriteNullTagLiteral (string name)
  417. {
  418. WriteNullTagLiteral (name, String.Empty);
  419. }
  420. protected void WriteNullTagLiteral (string name, string ns)
  421. {
  422. WriteStartElement (name, ns);
  423. WriteAttribute ("xsi","nil", XmlSchema.InstanceNamespace, "true");
  424. WriteEndElement ();
  425. }
  426. protected void WritePotentiallyReferencingElement (string n, string ns, object o)
  427. {
  428. WritePotentiallyReferencingElement (n, ns, o, null, false, false);
  429. }
  430. protected void WritePotentiallyReferencingElement (string n, string ns, object o, Type ambientType)
  431. {
  432. WritePotentiallyReferencingElement (n, ns, o, ambientType, false, false);
  433. }
  434. protected void WritePotentiallyReferencingElement (string n, string ns, object o, Type ambientType, bool suppressReference)
  435. {
  436. WritePotentiallyReferencingElement (n, ns, o, ambientType, suppressReference, false);
  437. }
  438. protected void WritePotentiallyReferencingElement (string n, string ns, object o, Type ambientType, bool suppressReference, bool isNullable)
  439. {
  440. if (o == null)
  441. {
  442. if (isNullable) WriteNullTagEncoded (n, ns);
  443. return;
  444. }
  445. WriteStartElement (n, ns, true);
  446. CheckReferenceQueue ();
  447. if (callbacks.ContainsKey (o.GetType ()))
  448. {
  449. WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
  450. if (o.GetType ().IsEnum) {
  451. info.Callback (o);
  452. }
  453. else if (suppressReference) {
  454. Writer.WriteAttributeString ("id", GetId (o, false));
  455. if (ambientType != o.GetType ()) WriteXsiType(info.TypeName, info.TypeNs);
  456. info.Callback (o);
  457. }
  458. else {
  459. if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
  460. Writer.WriteAttributeString ("href", "#" + GetId (o, true));
  461. }
  462. }
  463. else
  464. {
  465. // Must be a primitive type
  466. TypeData td = TypeTranslator.GetTypeData (o.GetType ());
  467. if (td.SchemaType != SchemaTypes.Primitive)
  468. throw new InvalidOperationException ("Invalid type: " + o.GetType().FullName);
  469. WriteXsiType(td.XmlType, XmlSchema.Namespace);
  470. Writer.WriteString (XmlCustomFormatter.ToXmlString (td, o));
  471. }
  472. WriteEndElement ();
  473. }
  474. protected void WriteReferencedElements ()
  475. {
  476. if (referencedElements == null) return;
  477. if (callbacks == null) return;
  478. while (referencedElements.Count > 0)
  479. {
  480. object o = referencedElements.Dequeue ();
  481. TypeData td = TypeTranslator.GetTypeData (o.GetType ());
  482. WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
  483. WriteStartElement (info.TypeName, info.TypeNs, true);
  484. Writer.WriteAttributeString ("id", GetId (o, false));
  485. if (td.SchemaType != SchemaTypes.Array) // Array use its own "arrayType" attribute
  486. WriteXsiType(info.TypeName, info.TypeNs);
  487. info.Callback (o);
  488. WriteEndElement ();
  489. }
  490. }
  491. protected void WriteReferencingElement (string n, string ns, object o)
  492. {
  493. WriteReferencingElement (n, ns, o, false);
  494. }
  495. protected void WriteReferencingElement (string n, string ns, object o, bool isNullable)
  496. {
  497. if (o == null)
  498. {
  499. if (isNullable) WriteNullTagEncoded (n, ns);
  500. return;
  501. }
  502. else
  503. {
  504. CheckReferenceQueue ();
  505. if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
  506. Writer.WriteStartElement (n, ns);
  507. Writer.WriteAttributeString ("href", "#" + GetId (o, true));
  508. Writer.WriteEndElement ();
  509. }
  510. }
  511. void CheckReferenceQueue ()
  512. {
  513. if (referencedElements == null)
  514. {
  515. referencedElements = new Queue ();
  516. InitCallbacks ();
  517. }
  518. }
  519. protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable)
  520. {
  521. if (serializable == null)
  522. {
  523. if (isNullable) WriteNullTagLiteral (name, ns);
  524. return;
  525. }
  526. else
  527. {
  528. Writer.WriteStartElement (name, ns);
  529. serializable.WriteXml (Writer);
  530. Writer.WriteEndElement ();
  531. }
  532. }
  533. protected void WriteStartDocument ()
  534. {
  535. if (Writer.WriteState == WriteState.Start)
  536. Writer.WriteStartDocument ();
  537. }
  538. protected void WriteStartElement (string name)
  539. {
  540. WriteStartElement (name, String.Empty, null, false);
  541. }
  542. protected void WriteStartElement (string name, string ns)
  543. {
  544. WriteStartElement (name, ns, null, false);
  545. }
  546. protected void WriteStartElement (string name, string ns, bool writePrefixed)
  547. {
  548. WriteStartElement (name, ns, null, writePrefixed);
  549. }
  550. protected void WriteStartElement (string name, string ns, object o)
  551. {
  552. WriteStartElement (name, ns, o, false);
  553. }
  554. protected void WriteStartElement (string name, string ns, object o, bool writePrefixed)
  555. {
  556. if (o != null)
  557. {
  558. if (serializedObjects.Contains (o))
  559. throw new InvalidOperationException ("A cirtular reference was detected while serializing an object of type " + o.GetType().Name);
  560. else
  561. serializedObjects [o] = o;
  562. }
  563. WriteState oldState = Writer.WriteState;
  564. // Elements with schema namespace are always written prefixed
  565. if (ns == XmlSchema.Namespace) writePrefixed = true;
  566. if (writePrefixed && ns != string.Empty) {
  567. name = XmlCustomFormatter.FromXmlName (name);
  568. string prefix = Writer.LookupPrefix (ns);
  569. if (prefix == null) {
  570. if (ns == XmlSchema.Namespace) prefix = "xsd";
  571. else prefix = "q" + (++qnameCount);
  572. }
  573. Writer.WriteStartElement (prefix, name, ns);
  574. } else
  575. Writer.WriteStartElement (name, ns);
  576. if (topLevelElement)
  577. {
  578. if (namespaces != null) {
  579. foreach (XmlQualifiedName qn in namespaces)
  580. {
  581. if (qn.Namespace == XmlSchema.Namespace || qn.Namespace == XmlSchema.InstanceNamespace) {
  582. if (Writer.LookupPrefix (qn.Namespace) == qn.Name) continue;
  583. }
  584. else
  585. if (Writer.LookupPrefix (qn.Namespace) != null) continue;
  586. WriteAttribute ("xmlns",qn.Name,xmlNamespace,qn.Namespace);
  587. }
  588. }
  589. topLevelElement = false;
  590. }
  591. }
  592. protected void WriteTypedPrimitive (string name, string ns, object o, bool xsiType)
  593. {
  594. string value;
  595. TypeData td = TypeTranslator.GetTypeData (o.GetType ());
  596. name = XmlCustomFormatter.FromXmlName (name);
  597. Writer.WriteStartElement (name, ns);
  598. if (o is XmlQualifiedName)
  599. value = FromXmlQualifiedName ((XmlQualifiedName) o);
  600. else
  601. value = XmlCustomFormatter.ToXmlString (td, o);
  602. if (xsiType)
  603. {
  604. if (td.SchemaType != SchemaTypes.Primitive)
  605. throw new InvalidOperationException ("Invalid type: " + o.GetType().FullName);
  606. WriteXsiType (td.XmlType, XmlSchema.Namespace);
  607. }
  608. WriteValue (value);
  609. Writer.WriteEndElement ();
  610. }
  611. protected void WriteValue (byte[] value)
  612. {
  613. Writer.WriteBase64 (value, 0, value.Length);
  614. }
  615. protected void WriteValue (string value)
  616. {
  617. if (value != null)
  618. Writer.WriteString (value);
  619. }
  620. protected void WriteXmlAttribute (XmlNode node)
  621. {
  622. WriteXmlAttribute (node, null);
  623. }
  624. protected void WriteXmlAttribute (XmlNode node, object container)
  625. {
  626. XmlAttribute attr = node as XmlAttribute;
  627. if (attr == null)
  628. throw new InvalidOperationException ("The node must be either type XmlAttribute or a derived type.");
  629. if (attr.NamespaceURI == XmlSerializer.WsdlNamespace)
  630. {
  631. // The wsdl arrayType attribute needs special handling
  632. if (attr.LocalName == "arrayType") {
  633. string ns, type, dimensions;
  634. TypeTranslator.ParseArrayType (attr.Value, out type, out ns, out dimensions);
  635. string value = GetQualifiedName (type + dimensions, ns);
  636. WriteAttribute (attr.Prefix, attr.LocalName, attr.NamespaceURI, value);
  637. return;
  638. }
  639. }
  640. WriteAttribute (attr.Prefix, attr.LocalName, attr.NamespaceURI, attr.Value);
  641. }
  642. protected void WriteXsiType (string name, string ns)
  643. {
  644. if (ns != null && ns != string.Empty)
  645. WriteAttribute ("type", XmlSchema.InstanceNamespace, GetQualifiedName (name, ns));
  646. else
  647. WriteAttribute ("type", XmlSchema.InstanceNamespace, name);
  648. }
  649. #endregion
  650. class WriteCallbackInfo
  651. {
  652. public Type Type;
  653. public string TypeName;
  654. public string TypeNs;
  655. public XmlSerializationWriteCallback Callback;
  656. }
  657. }
  658. }