~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#region License
 
2
// Copyright (c) 2007 James Newton-King
 
3
//
 
4
// Permission is hereby granted, free of charge, to any person
 
5
// obtaining a copy of this software and associated documentation
 
6
// files (the "Software"), to deal in the Software without
 
7
// restriction, including without limitation the rights to use,
 
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
 
9
// copies of the Software, and to permit persons to whom the
 
10
// Software is furnished to do so, subject to the following
 
11
// conditions:
 
12
//
 
13
// The above copyright notice and this permission notice shall be
 
14
// included in all copies or substantial portions of the Software.
 
15
//
 
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
23
// OTHER DEALINGS IN THE SOFTWARE.
 
24
#endregion
 
25
 
 
26
#if (!(SILVERLIGHT || PORTABLE) || WINDOWS_PHONE)
 
27
using System;
 
28
using System.Collections.Generic;
 
29
using System.Globalization;
 
30
using System.Xml;
 
31
#if !NET20
 
32
using System.Xml.Linq;
 
33
#endif
 
34
using Newtonsoft.Json.Utilities;
 
35
#if NET20
 
36
using Newtonsoft.Json.Utilities.LinqBridge;
 
37
#else
 
38
using System.Linq;
 
39
#endif
 
40
 
 
41
namespace Newtonsoft.Json.Converters
 
42
{
 
43
  #region XmlNodeWrappers
 
44
#if !SILVERLIGHT && !NETFX_CORE
 
45
  internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument
 
46
  {
 
47
    private readonly XmlDocument _document;
 
48
 
 
49
    public XmlDocumentWrapper(XmlDocument document)
 
50
      : base(document)
 
51
    {
 
52
      _document = document;
 
53
    }
 
54
 
 
55
    public IXmlNode CreateComment(string data)
 
56
    {
 
57
      return new XmlNodeWrapper(_document.CreateComment(data));
 
58
    }
 
59
 
 
60
    public IXmlNode CreateTextNode(string text)
 
61
    {
 
62
      return new XmlNodeWrapper(_document.CreateTextNode(text));
 
63
    }
 
64
 
 
65
    public IXmlNode CreateCDataSection(string data)
 
66
    {
 
67
      return new XmlNodeWrapper(_document.CreateCDataSection(data));
 
68
    }
 
69
 
 
70
    public IXmlNode CreateWhitespace(string text)
 
71
    {
 
72
      return new XmlNodeWrapper(_document.CreateWhitespace(text));
 
73
    }
 
74
 
 
75
    public IXmlNode CreateSignificantWhitespace(string text)
 
76
    {
 
77
      return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text));
 
78
    }
 
79
 
 
80
    public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
 
81
    {
 
82
      return new XmlNodeWrapper(_document.CreateXmlDeclaration(version, encoding, standalone));
 
83
    }
 
84
 
 
85
    public IXmlNode CreateProcessingInstruction(string target, string data)
 
86
    {
 
87
      return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data));
 
88
    }
 
89
 
 
90
    public IXmlElement CreateElement(string elementName)
 
91
    {
 
92
      return new XmlElementWrapper(_document.CreateElement(elementName));
 
93
    }
 
94
 
 
95
    public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
 
96
    {
 
97
      return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri));
 
98
    }
 
99
 
 
100
    public IXmlNode CreateAttribute(string name, string value)
 
101
    {
 
102
      XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name));
 
103
      attribute.Value = value;
 
104
 
 
105
      return attribute;
 
106
    }
 
107
 
 
108
    public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
 
109
    {
 
110
      XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri));
 
111
      attribute.Value = value;
 
112
 
 
113
      return attribute;
 
114
    }
 
115
 
 
116
    public IXmlElement DocumentElement
 
117
    {
 
118
      get
 
119
      {
 
120
        if (_document.DocumentElement == null)
 
121
          return null;
 
122
 
 
123
        return new XmlElementWrapper(_document.DocumentElement);
 
124
      }
 
125
    }
 
126
  }
 
127
 
 
128
  internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement
 
129
  {
 
130
    private readonly XmlElement _element;
 
131
 
 
132
    public XmlElementWrapper(XmlElement element)
 
133
      : base(element)
 
134
    {
 
135
      _element = element;
 
136
    }
 
137
 
 
138
    public void SetAttributeNode(IXmlNode attribute)
 
139
    {
 
140
      XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute;
 
141
 
 
142
      _element.SetAttributeNode((XmlAttribute) xmlAttributeWrapper.WrappedNode);
 
143
    }
 
144
 
 
145
    public string GetPrefixOfNamespace(string namespaceUri)
 
146
    {
 
147
      return _element.GetPrefixOfNamespace(namespaceUri);
 
148
    }
 
149
  }
 
150
 
 
151
  internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration
 
152
  {
 
153
    private readonly XmlDeclaration _declaration;
 
154
 
 
155
    public XmlDeclarationWrapper(XmlDeclaration declaration)
 
156
      : base(declaration)
 
157
    {
 
158
      _declaration = declaration;
 
159
    }
 
160
 
 
161
    public string Version
 
162
    {
 
163
      get { return _declaration.Version; }
 
164
    }
 
165
 
 
166
    public string Encoding
 
167
    {
 
168
      get { return _declaration.Encoding; }
 
169
      set { _declaration.Encoding = value; }
 
170
    }
 
171
 
 
172
    public string Standalone
 
173
    {
 
174
      get { return _declaration.Standalone; }
 
175
      set { _declaration.Standalone = value; }
 
176
    }
 
177
  }
 
178
 
 
179
  internal class XmlNodeWrapper : IXmlNode
 
180
  {
 
181
    private readonly XmlNode _node;
 
182
 
 
183
    public XmlNodeWrapper(XmlNode node)
 
184
    {
 
185
      _node = node;
 
186
    }
 
187
 
 
188
    public object WrappedNode
 
189
    {
 
190
      get { return _node; }
 
191
    }
 
192
 
 
193
    public XmlNodeType NodeType
 
194
    {
 
195
      get { return _node.NodeType; }
 
196
    }
 
197
 
 
198
    public string Name
 
199
    {
 
200
      get { return _node.Name; }
 
201
    }
 
202
 
 
203
    public string LocalName
 
204
    {
 
205
      get { return _node.LocalName; }
 
206
    }
 
207
 
 
208
    public IList<IXmlNode> ChildNodes
 
209
    {
 
210
      get { return _node.ChildNodes.Cast<XmlNode>().Select(n => WrapNode(n)).ToList(); }
 
211
    }
 
212
 
 
213
    private IXmlNode WrapNode(XmlNode node)
 
214
    {
 
215
      switch (node.NodeType)
 
216
      {
 
217
        case XmlNodeType.Element:
 
218
          return new XmlElementWrapper((XmlElement) node);
 
219
        case XmlNodeType.XmlDeclaration:
 
220
          return new XmlDeclarationWrapper((XmlDeclaration) node);
 
221
        default:
 
222
          return new XmlNodeWrapper(node);
 
223
      }
 
224
    }
 
225
 
 
226
    public IList<IXmlNode> Attributes
 
227
    {
 
228
      get
 
229
      {
 
230
        if (_node.Attributes == null)
 
231
          return null;
 
232
 
 
233
        return _node.Attributes.Cast<XmlAttribute>().Select(a => WrapNode(a)).ToList();
 
234
      }
 
235
    }
 
236
 
 
237
    public IXmlNode ParentNode
 
238
    {
 
239
      get
 
240
      {
 
241
        XmlNode node = (_node is XmlAttribute)
 
242
                         ? ((XmlAttribute) _node).OwnerElement
 
243
                         : _node.ParentNode;
 
244
        
 
245
        if (node == null)
 
246
          return null;
 
247
 
 
248
        return WrapNode(node);
 
249
      }
 
250
    }
 
251
 
 
252
    public string Value
 
253
    {
 
254
      get { return _node.Value; }
 
255
      set { _node.Value = value; }
 
256
    }
 
257
 
 
258
    public IXmlNode AppendChild(IXmlNode newChild)
 
259
    {
 
260
      XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper) newChild;
 
261
      _node.AppendChild(xmlNodeWrapper._node);
 
262
 
 
263
      return newChild;
 
264
    }
 
265
 
 
266
    public string Prefix
 
267
    {
 
268
      get { return _node.Prefix; }
 
269
    }
 
270
 
 
271
    public string NamespaceUri
 
272
    {
 
273
      get { return _node.NamespaceURI; }
 
274
    }
 
275
  }
 
276
#endif
 
277
  #endregion
 
278
 
 
279
  #region Interfaces
 
280
  internal interface IXmlDocument : IXmlNode
 
281
  {
 
282
    IXmlNode CreateComment(string text);
 
283
    IXmlNode CreateTextNode(string text);
 
284
    IXmlNode CreateCDataSection(string data);
 
285
    IXmlNode CreateWhitespace(string text);
 
286
    IXmlNode CreateSignificantWhitespace(string text);
 
287
    IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone);
 
288
    IXmlNode CreateProcessingInstruction(string target, string data);
 
289
    IXmlElement CreateElement(string elementName);
 
290
    IXmlElement CreateElement(string qualifiedName, string namespaceUri);
 
291
    IXmlNode CreateAttribute(string name, string value);
 
292
    IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value);
 
293
 
 
294
    IXmlElement DocumentElement { get; }
 
295
  }
 
296
 
 
297
  internal interface IXmlDeclaration : IXmlNode
 
298
  {
 
299
    string Version { get; }
 
300
    string Encoding { get; set; }
 
301
    string Standalone { get; set; }
 
302
  }
 
303
 
 
304
  internal interface IXmlElement : IXmlNode
 
305
  {
 
306
    void SetAttributeNode(IXmlNode attribute);
 
307
    string GetPrefixOfNamespace(string namespaceUri);
 
308
  }
 
309
 
 
310
  internal interface IXmlNode
 
311
  {
 
312
    XmlNodeType NodeType { get; }
 
313
    string LocalName { get; }
 
314
    IList<IXmlNode> ChildNodes { get; }
 
315
    IList<IXmlNode> Attributes { get; }
 
316
    IXmlNode ParentNode { get; }
 
317
    string Value { get; set; }
 
318
    IXmlNode AppendChild(IXmlNode newChild);
 
319
    string NamespaceUri { get; }
 
320
    object WrappedNode { get; }
 
321
  }
 
322
  #endregion
 
323
 
 
324
  #region XNodeWrappers
 
325
#if !NET20
 
326
  internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration
 
327
  {
 
328
    internal XDeclaration Declaration { get; private set; }
 
329
 
 
330
    public XDeclarationWrapper(XDeclaration declaration)
 
331
      : base(null)
 
332
    {
 
333
      Declaration = declaration;
 
334
    }
 
335
 
 
336
    public override XmlNodeType NodeType
 
337
    {
 
338
      get { return XmlNodeType.XmlDeclaration; }
 
339
    }
 
340
 
 
341
    public string Version
 
342
    {
 
343
      get { return Declaration.Version; }
 
344
    }
 
345
 
 
346
    public string Encoding
 
347
    {
 
348
      get { return Declaration.Encoding; }
 
349
      set { Declaration.Encoding = value; }
 
350
    }
 
351
 
 
352
    public string Standalone
 
353
    {
 
354
      get { return Declaration.Standalone; }
 
355
      set { Declaration.Standalone = value; }
 
356
    }
 
357
  }
 
358
 
 
359
  internal class XDocumentWrapper : XContainerWrapper, IXmlDocument
 
360
  {
 
361
    private XDocument Document
 
362
    {
 
363
      get { return (XDocument)WrappedNode; }
 
364
    }
 
365
 
 
366
    public XDocumentWrapper(XDocument document)
 
367
      : base(document)
 
368
    {
 
369
    }
 
370
 
 
371
    public override IList<IXmlNode> ChildNodes
 
372
    {
 
373
      get
 
374
      {
 
375
        IList<IXmlNode> childNodes = base.ChildNodes;
 
376
 
 
377
        if (Document.Declaration != null)
 
378
          childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration));
 
379
 
 
380
        return childNodes;
 
381
      }
 
382
    }
 
383
 
 
384
    public IXmlNode CreateComment(string text)
 
385
    {
 
386
      return new XObjectWrapper(new XComment(text));
 
387
    }
 
388
 
 
389
    public IXmlNode CreateTextNode(string text)
 
390
    {
 
391
      return new XObjectWrapper(new XText(text));
 
392
    }
 
393
 
 
394
    public IXmlNode CreateCDataSection(string data)
 
395
    {
 
396
      return new XObjectWrapper(new XCData(data));
 
397
    }
 
398
 
 
399
    public IXmlNode CreateWhitespace(string text)
 
400
    {
 
401
      return new XObjectWrapper(new XText(text));
 
402
    }
 
403
 
 
404
    public IXmlNode CreateSignificantWhitespace(string text)
 
405
    {
 
406
      return new XObjectWrapper(new XText(text));
 
407
    }
 
408
 
 
409
    public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
 
410
    {
 
411
      return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone));
 
412
    }
 
413
 
 
414
    public IXmlNode CreateProcessingInstruction(string target, string data)
 
415
    {
 
416
      return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data));
 
417
    }
 
418
 
 
419
    public IXmlElement CreateElement(string elementName)
 
420
    {
 
421
      return new XElementWrapper(new XElement(elementName));
 
422
    }
 
423
 
 
424
    public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
 
425
    {
 
426
      string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
 
427
      return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri)));
 
428
    }
 
429
 
 
430
    public IXmlNode CreateAttribute(string name, string value)
 
431
    {
 
432
      return new XAttributeWrapper(new XAttribute(name, value));
 
433
    }
 
434
 
 
435
    public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
 
436
    {
 
437
      string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
 
438
      return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value));
 
439
    }
 
440
 
 
441
    public IXmlElement DocumentElement
 
442
    {
 
443
      get
 
444
      {
 
445
        if (Document.Root == null)
 
446
          return null;
 
447
 
 
448
        return new XElementWrapper(Document.Root);
 
449
      }
 
450
    }
 
451
 
 
452
    public override IXmlNode AppendChild(IXmlNode newChild)
 
453
    {
 
454
      XDeclarationWrapper declarationWrapper = newChild as XDeclarationWrapper;
 
455
      if (declarationWrapper != null)
 
456
      {
 
457
        Document.Declaration = declarationWrapper.Declaration;
 
458
        return declarationWrapper;
 
459
      }
 
460
      else
 
461
      {
 
462
        return base.AppendChild(newChild);
 
463
      }
 
464
    }
 
465
  }
 
466
 
 
467
  internal class XTextWrapper : XObjectWrapper
 
468
  {
 
469
    private XText Text
 
470
    {
 
471
      get { return (XText)WrappedNode; }
 
472
    }
 
473
 
 
474
    public XTextWrapper(XText text)
 
475
      : base(text)
 
476
    {
 
477
    }
 
478
 
 
479
    public override string Value
 
480
    {
 
481
      get { return Text.Value; }
 
482
      set { Text.Value = value; }
 
483
    }
 
484
 
 
485
    public override IXmlNode ParentNode
 
486
    {
 
487
      get
 
488
      {
 
489
        if (Text.Parent == null)
 
490
          return null;
 
491
        
 
492
        return XContainerWrapper.WrapNode(Text.Parent);
 
493
      }
 
494
    }
 
495
  }
 
496
 
 
497
  internal class XCommentWrapper : XObjectWrapper
 
498
  {
 
499
    private XComment Text
 
500
    {
 
501
      get { return (XComment)WrappedNode; }
 
502
    }
 
503
 
 
504
    public XCommentWrapper(XComment text)
 
505
      : base(text)
 
506
    {
 
507
    }
 
508
 
 
509
    public override string Value
 
510
    {
 
511
      get { return Text.Value; }
 
512
      set { Text.Value = value; }
 
513
    }
 
514
 
 
515
    public override IXmlNode ParentNode
 
516
    {
 
517
      get
 
518
      {
 
519
        if (Text.Parent == null)
 
520
          return null;
 
521
 
 
522
        return XContainerWrapper.WrapNode(Text.Parent);
 
523
      }
 
524
    }
 
525
  }
 
526
 
 
527
  internal class XProcessingInstructionWrapper : XObjectWrapper
 
528
  {
 
529
    private XProcessingInstruction ProcessingInstruction
 
530
    {
 
531
      get { return (XProcessingInstruction)WrappedNode; }
 
532
    }
 
533
 
 
534
    public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction)
 
535
      : base(processingInstruction)
 
536
    {
 
537
    }
 
538
 
 
539
    public override string LocalName
 
540
    {
 
541
      get { return ProcessingInstruction.Target; }
 
542
    }
 
543
 
 
544
    public override string Value
 
545
    {
 
546
      get { return ProcessingInstruction.Data; }
 
547
      set { ProcessingInstruction.Data = value; }
 
548
    }
 
549
  }
 
550
 
 
551
  internal class XContainerWrapper : XObjectWrapper
 
552
  {
 
553
    private XContainer Container
 
554
    {
 
555
      get { return (XContainer)WrappedNode; }
 
556
    }
 
557
 
 
558
    public XContainerWrapper(XContainer container)
 
559
      : base(container)
 
560
    {
 
561
    }
 
562
 
 
563
    public override IList<IXmlNode> ChildNodes
 
564
    {
 
565
      get { return Container.Nodes().Select(n => WrapNode(n)).ToList(); }
 
566
    }
 
567
 
 
568
    public override IXmlNode ParentNode
 
569
    {
 
570
      get
 
571
      {
 
572
        if (Container.Parent == null)
 
573
          return null;
 
574
        
 
575
        return WrapNode(Container.Parent);
 
576
      }
 
577
    }
 
578
 
 
579
    internal static IXmlNode WrapNode(XObject node)
 
580
    {
 
581
      if (node is XDocument)
 
582
        return new XDocumentWrapper((XDocument)node);
 
583
      else if (node is XElement)
 
584
        return new XElementWrapper((XElement)node);
 
585
      else if (node is XContainer)
 
586
        return new XContainerWrapper((XContainer)node);
 
587
      else if (node is XProcessingInstruction)
 
588
        return new XProcessingInstructionWrapper((XProcessingInstruction)node);
 
589
      else if (node is XText)
 
590
        return new XTextWrapper((XText)node);
 
591
      else if (node is XComment)
 
592
        return new XCommentWrapper((XComment)node);
 
593
      else if (node is XAttribute)
 
594
        return new XAttributeWrapper((XAttribute) node);
 
595
      else
 
596
        return new XObjectWrapper(node);
 
597
    }
 
598
 
 
599
    public override IXmlNode AppendChild(IXmlNode newChild)
 
600
    {
 
601
      Container.Add(newChild.WrappedNode);
 
602
      return newChild;
 
603
    }
 
604
  }
 
605
 
 
606
  internal class XObjectWrapper : IXmlNode
 
607
  {
 
608
    private readonly XObject _xmlObject;
 
609
 
 
610
    public XObjectWrapper(XObject xmlObject)
 
611
    {
 
612
      _xmlObject = xmlObject;
 
613
    }
 
614
 
 
615
    public object WrappedNode
 
616
    {
 
617
      get { return _xmlObject; }
 
618
    }
 
619
 
 
620
    public virtual XmlNodeType NodeType
 
621
    {
 
622
      get { return _xmlObject.NodeType; }
 
623
    }
 
624
 
 
625
    public virtual string LocalName
 
626
    {
 
627
      get { return null; }
 
628
    }
 
629
 
 
630
    public virtual IList<IXmlNode> ChildNodes
 
631
    {
 
632
      get { return new List<IXmlNode>(); }
 
633
    }
 
634
 
 
635
    public virtual IList<IXmlNode> Attributes
 
636
    {
 
637
      get { return null; }
 
638
    }
 
639
 
 
640
    public virtual IXmlNode ParentNode
 
641
    {
 
642
      get { return null; }
 
643
    }
 
644
 
 
645
    public virtual string Value
 
646
    {
 
647
      get { return null; }
 
648
      set { throw new InvalidOperationException(); }
 
649
    }
 
650
 
 
651
    public virtual IXmlNode AppendChild(IXmlNode newChild)
 
652
    {
 
653
      throw new InvalidOperationException();
 
654
    }
 
655
 
 
656
    public virtual string NamespaceUri
 
657
    {
 
658
      get { return null; }
 
659
    }
 
660
  }
 
661
 
 
662
  internal class XAttributeWrapper : XObjectWrapper
 
663
  {
 
664
    private XAttribute Attribute
 
665
    {
 
666
      get { return (XAttribute)WrappedNode; }
 
667
    }
 
668
 
 
669
    public XAttributeWrapper(XAttribute attribute)
 
670
      : base(attribute)
 
671
    {
 
672
    }
 
673
 
 
674
    public override string Value
 
675
    {
 
676
      get { return Attribute.Value; }
 
677
      set { Attribute.Value = value; }
 
678
    }
 
679
 
 
680
    public override string LocalName
 
681
    {
 
682
      get { return Attribute.Name.LocalName; }
 
683
    }
 
684
 
 
685
    public override string NamespaceUri
 
686
    {
 
687
      get { return Attribute.Name.NamespaceName; }
 
688
    }
 
689
 
 
690
    public override IXmlNode ParentNode
 
691
    {
 
692
      get
 
693
      {
 
694
        if (Attribute.Parent == null)
 
695
          return null;
 
696
 
 
697
        return XContainerWrapper.WrapNode(Attribute.Parent);
 
698
      }
 
699
    }
 
700
  }
 
701
 
 
702
  internal class XElementWrapper : XContainerWrapper, IXmlElement
 
703
  {
 
704
    private XElement Element
 
705
    {
 
706
      get { return (XElement) WrappedNode; }
 
707
    }
 
708
 
 
709
    public XElementWrapper(XElement element)
 
710
      : base(element)
 
711
    {
 
712
    }
 
713
 
 
714
    public void SetAttributeNode(IXmlNode attribute)
 
715
    {
 
716
      XObjectWrapper wrapper = (XObjectWrapper)attribute;
 
717
      Element.Add(wrapper.WrappedNode);
 
718
    }
 
719
 
 
720
    public override IList<IXmlNode> Attributes
 
721
    {
 
722
      get { return Element.Attributes().Select(a => new XAttributeWrapper(a)).Cast<IXmlNode>().ToList(); }
 
723
    }
 
724
 
 
725
    public override string Value
 
726
    {
 
727
      get { return Element.Value; }
 
728
      set { Element.Value = value; }
 
729
    }
 
730
 
 
731
    public override string LocalName
 
732
    {
 
733
      get { return Element.Name.LocalName; }
 
734
    }
 
735
 
 
736
    public override string NamespaceUri
 
737
    {
 
738
      get { return Element.Name.NamespaceName; }
 
739
    }
 
740
 
 
741
    public string GetPrefixOfNamespace(string namespaceUri)
 
742
    {
 
743
      return Element.GetPrefixOfNamespace(namespaceUri);
 
744
    }
 
745
  }
 
746
#endif
 
747
  #endregion
 
748
 
 
749
  /// <summary>
 
750
  /// Converts XML to and from JSON.
 
751
  /// </summary>
 
752
  public class XmlNodeConverter : JsonConverter
 
753
  {
 
754
    private const string TextName = "#text";
 
755
    private const string CommentName = "#comment";
 
756
    private const string CDataName = "#cdata-section";
 
757
    private const string WhitespaceName = "#whitespace";
 
758
    private const string SignificantWhitespaceName = "#significant-whitespace";
 
759
    private const string DeclarationName = "?xml";
 
760
    private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
 
761
 
 
762
    /// <summary>
 
763
    /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
 
764
    /// </summary>
 
765
    /// <value>The name of the deserialize root element.</value>
 
766
    public string DeserializeRootElementName { get; set; }
 
767
 
 
768
    /// <summary>
 
769
    /// Gets or sets a flag to indicate whether to write the Json.NET array attribute.
 
770
    /// This attribute helps preserve arrays when converting the written XML back to JSON.
 
771
    /// </summary>
 
772
    /// <value><c>true</c> if the array attibute is written to the XML; otherwise, <c>false</c>.</value>
 
773
    public bool WriteArrayAttribute { get; set; }
 
774
 
 
775
    /// <summary>
 
776
    /// Gets or sets a value indicating whether to write the root JSON object.
 
777
    /// </summary>
 
778
    /// <value><c>true</c> if the JSON root object is omitted; otherwise, <c>false</c>.</value>
 
779
    public bool OmitRootObject { get; set; }
 
780
 
 
781
    #region Writing
 
782
    /// <summary>
 
783
    /// Writes the JSON representation of the object.
 
784
    /// </summary>
 
785
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
 
786
    /// <param name="serializer">The calling serializer.</param>
 
787
    /// <param name="value">The value.</param>
 
788
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
 
789
    {
 
790
      IXmlNode node = WrapXml(value);
 
791
 
 
792
      XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
 
793
      PushParentNamespaces(node, manager);
 
794
 
 
795
      if (!OmitRootObject)
 
796
        writer.WriteStartObject();
 
797
 
 
798
      SerializeNode(writer, node, manager, !OmitRootObject);
 
799
      
 
800
      if (!OmitRootObject)
 
801
        writer.WriteEndObject();
 
802
    }
 
803
 
 
804
    private IXmlNode WrapXml(object value)
 
805
    {
 
806
#if !NET20
 
807
      if (value is XObject)
 
808
        return XContainerWrapper.WrapNode((XObject)value);
 
809
#endif
 
810
#if !(SILVERLIGHT || NETFX_CORE)
 
811
      if (value is XmlNode)
 
812
        return new XmlNodeWrapper((XmlNode)value);
 
813
#endif
 
814
      
 
815
      throw new ArgumentException("Value must be an XML object.", "value");
 
816
    }
 
817
 
 
818
    private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
 
819
    {
 
820
      List<IXmlNode> parentElements = null;
 
821
 
 
822
      IXmlNode parent = node;
 
823
      while ((parent = parent.ParentNode) != null)
 
824
      {
 
825
        if (parent.NodeType == XmlNodeType.Element)
 
826
        {
 
827
          if (parentElements == null)
 
828
            parentElements = new List<IXmlNode>();
 
829
 
 
830
          parentElements.Add(parent);
 
831
        }
 
832
      }
 
833
 
 
834
      if (parentElements != null)
 
835
      {
 
836
        parentElements.Reverse();
 
837
 
 
838
        foreach (IXmlNode parentElement in parentElements)
 
839
        {
 
840
          manager.PushScope();
 
841
          foreach (IXmlNode attribute in parentElement.Attributes)
 
842
          {
 
843
            if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns")
 
844
              manager.AddNamespace(attribute.LocalName, attribute.Value);
 
845
          }
 
846
        }
 
847
      }
 
848
    }
 
849
 
 
850
    private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
 
851
    {
 
852
      string prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/"))
 
853
                        ? null
 
854
                        : manager.LookupPrefix(node.NamespaceUri);
 
855
 
 
856
      if (!string.IsNullOrEmpty(prefix))
 
857
        return prefix + ":" + node.LocalName;
 
858
      else
 
859
        return node.LocalName;
 
860
    }
 
861
 
 
862
    private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager)
 
863
    {
 
864
      switch (node.NodeType)
 
865
      {
 
866
        case XmlNodeType.Attribute:
 
867
          if (node.NamespaceUri == JsonNamespaceUri)
 
868
            return "$" + node.LocalName;
 
869
          else
 
870
            return "@" + ResolveFullName(node, manager);
 
871
        case XmlNodeType.CDATA:
 
872
          return CDataName;
 
873
        case XmlNodeType.Comment:
 
874
          return CommentName;
 
875
        case XmlNodeType.Element:
 
876
          return ResolveFullName(node, manager);
 
877
        case XmlNodeType.ProcessingInstruction:
 
878
          return "?" + ResolveFullName(node, manager);
 
879
        case XmlNodeType.XmlDeclaration:
 
880
          return DeclarationName;
 
881
        case XmlNodeType.SignificantWhitespace:
 
882
          return SignificantWhitespaceName;
 
883
        case XmlNodeType.Text:
 
884
          return TextName;
 
885
        case XmlNodeType.Whitespace:
 
886
          return WhitespaceName;
 
887
        default:
 
888
          throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
 
889
      }
 
890
    }
 
891
 
 
892
    private bool IsArray(IXmlNode node)
 
893
    {
 
894
      IXmlNode jsonArrayAttribute = (node.Attributes != null)
 
895
                                      ? node.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceUri == JsonNamespaceUri)
 
896
                                      : null;
 
897
      
 
898
      return (jsonArrayAttribute != null && XmlConvert.ToBoolean(jsonArrayAttribute.Value));
 
899
    }
 
900
 
 
901
    private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
 
902
    {
 
903
      // group nodes together by name
 
904
      Dictionary<string, List<IXmlNode>> nodesGroupedByName = new Dictionary<string, List<IXmlNode>>();
 
905
 
 
906
      for (int i = 0; i < node.ChildNodes.Count; i++)
 
907
      {
 
908
        IXmlNode childNode = node.ChildNodes[i];
 
909
        string nodeName = GetPropertyName(childNode, manager);
 
910
 
 
911
        List<IXmlNode> nodes;
 
912
        if (!nodesGroupedByName.TryGetValue(nodeName, out nodes))
 
913
        {
 
914
          nodes = new List<IXmlNode>();
 
915
          nodesGroupedByName.Add(nodeName, nodes);
 
916
        }
 
917
 
 
918
        nodes.Add(childNode);
 
919
      }
 
920
 
 
921
      // loop through grouped nodes. write single name instances as normal,
 
922
      // write multiple names together in an array
 
923
      foreach (KeyValuePair<string, List<IXmlNode>> nodeNameGroup in nodesGroupedByName)
 
924
      {
 
925
        List<IXmlNode> groupedNodes = nodeNameGroup.Value;
 
926
        bool writeArray;
 
927
 
 
928
        if (groupedNodes.Count == 1)
 
929
        {
 
930
          writeArray = IsArray(groupedNodes[0]);
 
931
        }
 
932
        else
 
933
        {
 
934
          writeArray = true;
 
935
        }
 
936
 
 
937
        if (!writeArray)
 
938
        {
 
939
          SerializeNode(writer, groupedNodes[0], manager, writePropertyName);
 
940
        }
 
941
        else
 
942
        {
 
943
          string elementNames = nodeNameGroup.Key;
 
944
 
 
945
          if (writePropertyName)
 
946
            writer.WritePropertyName(elementNames);
 
947
 
 
948
          writer.WriteStartArray();
 
949
 
 
950
          for (int i = 0; i < groupedNodes.Count; i++)
 
951
          {
 
952
            SerializeNode(writer, groupedNodes[i], manager, false);
 
953
          }
 
954
 
 
955
          writer.WriteEndArray();
 
956
        }
 
957
      }
 
958
    }
 
959
 
 
960
    private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
 
961
    {
 
962
      switch (node.NodeType)
 
963
      {
 
964
        case XmlNodeType.Document:
 
965
        case XmlNodeType.DocumentFragment:
 
966
          SerializeGroupedNodes(writer, node, manager, writePropertyName);
 
967
          break;
 
968
        case XmlNodeType.Element:
 
969
          if (IsArray(node) && node.ChildNodes.All(n => n.LocalName == node.LocalName) && node.ChildNodes.Count > 0)
 
970
          {
 
971
            SerializeGroupedNodes(writer, node, manager, false);
 
972
          }
 
973
          else
 
974
          {
 
975
            foreach (IXmlNode attribute in node.Attributes)
 
976
            {
 
977
              if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/")
 
978
              {
 
979
                string prefix = (attribute.LocalName != "xmlns")
 
980
                                  ? attribute.LocalName
 
981
                                  : string.Empty;
 
982
 
 
983
                manager.AddNamespace(prefix, attribute.Value);
 
984
              }
 
985
            }
 
986
 
 
987
            if (writePropertyName)
 
988
              writer.WritePropertyName(GetPropertyName(node, manager));
 
989
 
 
990
            if (!ValueAttributes(node.Attributes).Any() && node.ChildNodes.Count == 1
 
991
                && node.ChildNodes[0].NodeType == XmlNodeType.Text)
 
992
            {
 
993
              // write elements with a single text child as a name value pair
 
994
              writer.WriteValue(node.ChildNodes[0].Value);
 
995
            }
 
996
            else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
 
997
            {
 
998
              // empty element
 
999
              writer.WriteNull();
 
1000
            }
 
1001
            else
 
1002
            {
 
1003
              writer.WriteStartObject();
 
1004
 
 
1005
              for (int i = 0; i < node.Attributes.Count; i++)
 
1006
              {
 
1007
                SerializeNode(writer, node.Attributes[i], manager, true);
 
1008
              }
 
1009
 
 
1010
              SerializeGroupedNodes(writer, node, manager, true);
 
1011
 
 
1012
              writer.WriteEndObject();
 
1013
            }
 
1014
          }
 
1015
 
 
1016
          break;
 
1017
        case XmlNodeType.Comment:
 
1018
          if (writePropertyName)
 
1019
            writer.WriteComment(node.Value);
 
1020
          break;
 
1021
        case XmlNodeType.Attribute:
 
1022
        case XmlNodeType.Text:
 
1023
        case XmlNodeType.CDATA:
 
1024
        case XmlNodeType.ProcessingInstruction:
 
1025
        case XmlNodeType.Whitespace:
 
1026
        case XmlNodeType.SignificantWhitespace:
 
1027
          if (node.NamespaceUri == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
 
1028
            return;
 
1029
 
 
1030
          if (node.NamespaceUri == JsonNamespaceUri)
 
1031
          {
 
1032
            if (node.LocalName == "Array")
 
1033
              return;
 
1034
          }
 
1035
 
 
1036
          if (writePropertyName)
 
1037
            writer.WritePropertyName(GetPropertyName(node, manager));
 
1038
          writer.WriteValue(node.Value);
 
1039
          break;
 
1040
        case XmlNodeType.XmlDeclaration:
 
1041
          IXmlDeclaration declaration = (IXmlDeclaration)node;
 
1042
          writer.WritePropertyName(GetPropertyName(node, manager));
 
1043
          writer.WriteStartObject();
 
1044
 
 
1045
          if (!string.IsNullOrEmpty(declaration.Version))
 
1046
          {
 
1047
            writer.WritePropertyName("@version");
 
1048
            writer.WriteValue(declaration.Version);
 
1049
          }
 
1050
          if (!string.IsNullOrEmpty(declaration.Encoding))
 
1051
          {
 
1052
            writer.WritePropertyName("@encoding");
 
1053
            writer.WriteValue(declaration.Encoding);
 
1054
          }
 
1055
          if (!string.IsNullOrEmpty(declaration.Standalone))
 
1056
          {
 
1057
            writer.WritePropertyName("@standalone");
 
1058
            writer.WriteValue(declaration.Standalone);
 
1059
          }
 
1060
 
 
1061
          writer.WriteEndObject();
 
1062
          break;
 
1063
        default:
 
1064
          throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
 
1065
      }
 
1066
    }
 
1067
    #endregion
 
1068
 
 
1069
    #region Reading
 
1070
    /// <summary>
 
1071
    /// Reads the JSON representation of the object.
 
1072
    /// </summary>
 
1073
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
 
1074
    /// <param name="objectType">Type of the object.</param>
 
1075
    /// <param name="existingValue">The existing value of object being read.</param>
 
1076
    /// <param name="serializer">The calling serializer.</param>
 
1077
    /// <returns>The object value.</returns>
 
1078
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
 
1079
    {
 
1080
      XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
 
1081
      IXmlDocument document = null;
 
1082
      IXmlNode rootNode = null;
 
1083
 
 
1084
#if !NET20
 
1085
      if (typeof(XObject).IsAssignableFrom(objectType))
 
1086
      {
 
1087
        if (objectType != typeof (XDocument) && objectType != typeof (XElement))
 
1088
          throw new JsonSerializationException("XmlNodeConverter only supports deserializing XDocument or XElement.");
 
1089
 
 
1090
        XDocument d = new XDocument();
 
1091
        document = new XDocumentWrapper(d);
 
1092
        rootNode = document;
 
1093
      }
 
1094
#endif
 
1095
#if !(SILVERLIGHT || NETFX_CORE)
 
1096
      if (typeof(XmlNode).IsAssignableFrom(objectType))
 
1097
      {
 
1098
        if (objectType != typeof (XmlDocument))
 
1099
          throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
 
1100
 
 
1101
        XmlDocument d = new XmlDocument();
 
1102
        document = new XmlDocumentWrapper(d);
 
1103
        rootNode = document;
 
1104
      }
 
1105
#endif
 
1106
      
 
1107
      if (document == null || rootNode == null)
 
1108
        throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
 
1109
 
 
1110
      if (reader.TokenType != JsonToken.StartObject)
 
1111
        throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
 
1112
 
 
1113
      if (!string.IsNullOrEmpty(DeserializeRootElementName))
 
1114
      {
 
1115
        //rootNode = document.CreateElement(DeserializeRootElementName);
 
1116
        //document.AppendChild(rootNode);
 
1117
        ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
 
1118
      }
 
1119
      else
 
1120
      {
 
1121
        reader.Read();
 
1122
        DeserializeNode(reader, document, manager, rootNode);
 
1123
      }
 
1124
 
 
1125
#if !NET20
 
1126
      if (objectType == typeof(XElement))
 
1127
      {
 
1128
        XElement element = (XElement)document.DocumentElement.WrappedNode;
 
1129
        element.Remove();
 
1130
 
 
1131
        return element;
 
1132
      }
 
1133
#endif
 
1134
 
 
1135
      return document.WrappedNode;
 
1136
    }
 
1137
 
 
1138
    private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode)
 
1139
    {
 
1140
      switch (propertyName)
 
1141
      {
 
1142
        case TextName:
 
1143
          currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
 
1144
          break;
 
1145
        case CDataName:
 
1146
          currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
 
1147
          break;
 
1148
        case WhitespaceName:
 
1149
          currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
 
1150
          break;
 
1151
        case SignificantWhitespaceName:
 
1152
          currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
 
1153
          break;
 
1154
        default:
 
1155
          // processing instructions and the xml declaration start with ?
 
1156
          if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
 
1157
          {
 
1158
            CreateInstruction(reader, document, currentNode, propertyName);
 
1159
          }
 
1160
          else
 
1161
          {
 
1162
            if (reader.TokenType == JsonToken.StartArray)
 
1163
            {
 
1164
              // handle nested arrays
 
1165
              ReadArrayElements(reader, document, propertyName, currentNode, manager);
 
1166
              return;
 
1167
            }
 
1168
 
 
1169
            // have to wait until attributes have been parsed before creating element
 
1170
            // attributes may contain namespace info used by the element
 
1171
            ReadElement(reader, document, currentNode, propertyName, manager);
 
1172
          }
 
1173
          break;
 
1174
      }
 
1175
    }
 
1176
 
 
1177
    private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
 
1178
    {
 
1179
      if (string.IsNullOrEmpty(propertyName))
 
1180
        throw new JsonSerializationException("XmlNodeConverter cannot convert JSON with an empty property name to XML.");
 
1181
 
 
1182
      Dictionary<string, string> attributeNameValues = ReadAttributeElements(reader, manager);
 
1183
 
 
1184
      string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
 
1185
 
 
1186
      if (propertyName.StartsWith("@"))
 
1187
      {
 
1188
        var attributeName = propertyName.Substring(1);
 
1189
        var attributeValue = reader.Value.ToString();
 
1190
 
 
1191
        var attributePrefix = MiscellaneousUtils.GetPrefix(attributeName);
 
1192
 
 
1193
        var attribute = (!string.IsNullOrEmpty(attributePrefix))
 
1194
                                 ? document.CreateAttribute(attributeName, manager.LookupNamespace(attributePrefix), attributeValue)
 
1195
                                 : document.CreateAttribute(attributeName, attributeValue);
 
1196
 
 
1197
        ((IXmlElement)currentNode).SetAttributeNode(attribute);
 
1198
      }
 
1199
      else
 
1200
      {
 
1201
        IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
 
1202
 
 
1203
        currentNode.AppendChild(element);
 
1204
 
 
1205
        // add attributes to newly created element
 
1206
        foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
 
1207
        {
 
1208
          string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
 
1209
 
 
1210
          IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
 
1211
                                 ? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
 
1212
                                 : document.CreateAttribute(nameValue.Key, nameValue.Value);
 
1213
 
 
1214
          element.SetAttributeNode(attribute);
 
1215
        }
 
1216
 
 
1217
        if (reader.TokenType == JsonToken.String
 
1218
            || reader.TokenType == JsonToken.Integer
 
1219
            || reader.TokenType == JsonToken.Float
 
1220
            || reader.TokenType == JsonToken.Boolean
 
1221
            || reader.TokenType == JsonToken.Date)
 
1222
        {
 
1223
          element.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader)));
 
1224
        }
 
1225
        else if (reader.TokenType == JsonToken.Null)
 
1226
        {
 
1227
          // empty element. do nothing
 
1228
        }
 
1229
        else
 
1230
        {
 
1231
          // finished element will have no children to deserialize
 
1232
          if (reader.TokenType != JsonToken.EndObject)
 
1233
          {
 
1234
            manager.PushScope();
 
1235
 
 
1236
            DeserializeNode(reader, document, manager, element);
 
1237
 
 
1238
            manager.PopScope();
 
1239
          }
 
1240
        }
 
1241
      }
 
1242
    }
 
1243
 
 
1244
    private string ConvertTokenToXmlValue(JsonReader reader)
 
1245
    {
 
1246
      if (reader.TokenType == JsonToken.String)
 
1247
      {
 
1248
        return reader.Value.ToString();
 
1249
      }
 
1250
      else if (reader.TokenType == JsonToken.Integer)
 
1251
      {
 
1252
        return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
 
1253
      }
 
1254
      else if (reader.TokenType == JsonToken.Float)
 
1255
      {
 
1256
        return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
 
1257
      }
 
1258
      else if (reader.TokenType == JsonToken.Boolean)
 
1259
      {
 
1260
        return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
 
1261
      }
 
1262
      else if (reader.TokenType == JsonToken.Date)
 
1263
      {
 
1264
        DateTime d = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture);
 
1265
#if !NETFX_CORE
 
1266
        return XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind));
 
1267
#else
 
1268
        return XmlConvert.ToString(d);
 
1269
#endif   
 
1270
      }
 
1271
      else if (reader.TokenType == JsonToken.Null)
 
1272
      {
 
1273
        return null;
 
1274
      }
 
1275
      else
 
1276
      {
 
1277
        throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
 
1278
      }
 
1279
    }
 
1280
 
 
1281
    private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
 
1282
    {
 
1283
      string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
 
1284
 
 
1285
      IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
 
1286
 
 
1287
      currentNode.AppendChild(nestedArrayElement);
 
1288
 
 
1289
      int count = 0;
 
1290
      while (reader.Read() && reader.TokenType != JsonToken.EndArray)
 
1291
      {
 
1292
        DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
 
1293
        count++;
 
1294
      }
 
1295
 
 
1296
      if (WriteArrayAttribute)
 
1297
      {
 
1298
        AddJsonArrayAttribute(nestedArrayElement, document);
 
1299
      }
 
1300
 
 
1301
      if (count == 1 && WriteArrayAttribute)
 
1302
      {
 
1303
        IXmlElement arrayElement = nestedArrayElement.ChildNodes.CastValid<IXmlElement>().Single(n => n.LocalName == propertyName);
 
1304
        AddJsonArrayAttribute(arrayElement, document);
 
1305
      }
 
1306
    }
 
1307
 
 
1308
    private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document)
 
1309
    {
 
1310
      element.SetAttributeNode(document.CreateAttribute("json:Array", JsonNamespaceUri, "true"));
 
1311
 
 
1312
#if !NET20
 
1313
      // linq to xml doesn't automatically include prefixes via the namespace manager
 
1314
      if (element is XElementWrapper)
 
1315
      {
 
1316
        if (element.GetPrefixOfNamespace(JsonNamespaceUri) == null)
 
1317
        {
 
1318
          element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", JsonNamespaceUri));
 
1319
        }
 
1320
      }
 
1321
#endif
 
1322
    }
 
1323
 
 
1324
    private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
 
1325
    {
 
1326
      Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
 
1327
      bool finishedAttributes = false;
 
1328
      bool finishedElement = false;
 
1329
 
 
1330
      // a string token means the element only has a single text child
 
1331
      if (reader.TokenType != JsonToken.String
 
1332
          && reader.TokenType != JsonToken.Null
 
1333
          && reader.TokenType != JsonToken.Boolean
 
1334
          && reader.TokenType != JsonToken.Integer
 
1335
          && reader.TokenType != JsonToken.Float
 
1336
          && reader.TokenType != JsonToken.Date
 
1337
          && reader.TokenType != JsonToken.StartConstructor)
 
1338
      {
 
1339
        // read properties until first non-attribute is encountered
 
1340
        while (!finishedAttributes && !finishedElement && reader.Read())
 
1341
        {
 
1342
          switch (reader.TokenType)
 
1343
          {
 
1344
            case JsonToken.PropertyName:
 
1345
              string attributeName = reader.Value.ToString();
 
1346
 
 
1347
              if (!string.IsNullOrEmpty(attributeName))
 
1348
              {
 
1349
                char firstChar = attributeName[0];
 
1350
                string attributeValue;
 
1351
 
 
1352
                switch (firstChar)
 
1353
                {
 
1354
                  case '@':
 
1355
                    attributeName = attributeName.Substring(1);
 
1356
                    reader.Read();
 
1357
                    attributeValue = ConvertTokenToXmlValue(reader);
 
1358
                    attributeNameValues.Add(attributeName, attributeValue);
 
1359
 
 
1360
                    string namespacePrefix;
 
1361
                    if (IsNamespaceAttribute(attributeName, out namespacePrefix))
 
1362
                    {
 
1363
                      manager.AddNamespace(namespacePrefix, attributeValue);
 
1364
                    }
 
1365
                    break;
 
1366
                  case '$':
 
1367
                    attributeName = attributeName.Substring(1);
 
1368
                    reader.Read();
 
1369
                    attributeValue = reader.Value.ToString();
 
1370
 
 
1371
                    // check that JsonNamespaceUri is in scope
 
1372
                    // if it isn't then add it to document and namespace manager
 
1373
                    string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri);
 
1374
                    if (jsonPrefix == null)
 
1375
                    {
 
1376
                      // ensure that the prefix used is free
 
1377
                      int? i = null;
 
1378
                      while (manager.LookupNamespace("json" + i) != null)
 
1379
                      {
 
1380
                        i = i.GetValueOrDefault() + 1;
 
1381
                      }
 
1382
                      jsonPrefix = "json" + i;
 
1383
 
 
1384
                      attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri);
 
1385
                      manager.AddNamespace(jsonPrefix, JsonNamespaceUri);
 
1386
                    }
 
1387
 
 
1388
                    attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue);
 
1389
                    break;
 
1390
                  default:
 
1391
                    finishedAttributes = true;
 
1392
                    break;
 
1393
                }
 
1394
              }
 
1395
              else
 
1396
              {
 
1397
                finishedAttributes = true;
 
1398
              }
 
1399
 
 
1400
              break;
 
1401
            case JsonToken.EndObject:
 
1402
              finishedElement = true;
 
1403
              break;
 
1404
            default:
 
1405
              throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
 
1406
          }
 
1407
        }
 
1408
      }
 
1409
 
 
1410
      return attributeNameValues;
 
1411
    }
 
1412
 
 
1413
    private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
 
1414
    {
 
1415
      if (propertyName == DeclarationName)
 
1416
      {
 
1417
        string version = null;
 
1418
        string encoding = null;
 
1419
        string standalone = null;
 
1420
        while (reader.Read() && reader.TokenType != JsonToken.EndObject)
 
1421
        {
 
1422
          switch (reader.Value.ToString())
 
1423
          {
 
1424
            case "@version":
 
1425
              reader.Read();
 
1426
              version = reader.Value.ToString();
 
1427
              break;
 
1428
            case "@encoding":
 
1429
              reader.Read();
 
1430
              encoding = reader.Value.ToString();
 
1431
              break;
 
1432
            case "@standalone":
 
1433
              reader.Read();
 
1434
              standalone = reader.Value.ToString();
 
1435
              break;
 
1436
            default:
 
1437
              throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
 
1438
          }
 
1439
        }
 
1440
 
 
1441
        IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
 
1442
        currentNode.AppendChild(declaration);
 
1443
      }
 
1444
      else
 
1445
      {
 
1446
        IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
 
1447
        currentNode.AppendChild(instruction);
 
1448
      }
 
1449
    }
 
1450
 
 
1451
    private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
 
1452
    {
 
1453
      string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);
 
1454
 
 
1455
      IXmlElement element = (!string.IsNullOrEmpty(ns)) ? document.CreateElement(elementName, ns) : document.CreateElement(elementName);
 
1456
 
 
1457
      return element;
 
1458
    }
 
1459
 
 
1460
    private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
 
1461
    {
 
1462
      do
 
1463
      {
 
1464
        switch (reader.TokenType)
 
1465
        {
 
1466
          case JsonToken.PropertyName:
 
1467
            if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
 
1468
              throw new JsonSerializationException("JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifing a DeserializeRootElementName.");
 
1469
 
 
1470
            string propertyName = reader.Value.ToString();
 
1471
            reader.Read();
 
1472
 
 
1473
            if (reader.TokenType == JsonToken.StartArray)
 
1474
            {
 
1475
              int count = 0;
 
1476
              while (reader.Read() && reader.TokenType != JsonToken.EndArray)
 
1477
              {
 
1478
                DeserializeValue(reader, document, manager, propertyName, currentNode);
 
1479
                count++;
 
1480
              }
 
1481
 
 
1482
              if (count == 1 && WriteArrayAttribute)
 
1483
              {
 
1484
                IXmlElement arrayElement = currentNode.ChildNodes.CastValid<IXmlElement>().Single(n => n.LocalName == propertyName);
 
1485
                AddJsonArrayAttribute(arrayElement, document);
 
1486
              }
 
1487
            }
 
1488
            else
 
1489
            {
 
1490
              DeserializeValue(reader, document, manager, propertyName, currentNode);
 
1491
            }
 
1492
            break;
 
1493
          case JsonToken.StartConstructor:
 
1494
            string constructorName = reader.Value.ToString();
 
1495
 
 
1496
            while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
 
1497
            {
 
1498
              DeserializeValue(reader, document, manager, constructorName, currentNode);
 
1499
            }
 
1500
            break;
 
1501
          case JsonToken.Comment:
 
1502
            currentNode.AppendChild(document.CreateComment((string)reader.Value));
 
1503
            break;
 
1504
          case JsonToken.EndObject:
 
1505
          case JsonToken.EndArray:
 
1506
            return;
 
1507
          default:
 
1508
            throw new JsonSerializationException("Unexpected JsonToken when deserializing node: " + reader.TokenType);
 
1509
        }
 
1510
      } while (reader.TokenType == JsonToken.PropertyName || reader.Read());
 
1511
      // don't read if current token is a property. token was already read when parsing element attributes
 
1512
    }
 
1513
 
 
1514
    /// <summary>
 
1515
    /// Checks if the attributeName is a namespace attribute.
 
1516
    /// </summary>
 
1517
    /// <param name="attributeName">Attribute name to test.</param>
 
1518
    /// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
 
1519
    /// <returns>True if attribute name is for a namespace attribute, otherwise false.</returns>
 
1520
    private bool IsNamespaceAttribute(string attributeName, out string prefix)
 
1521
    {
 
1522
      if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
 
1523
      {
 
1524
        if (attributeName.Length == 5)
 
1525
        {
 
1526
          prefix = string.Empty;
 
1527
          return true;
 
1528
        }
 
1529
        else if (attributeName[5] == ':')
 
1530
        {
 
1531
          prefix = attributeName.Substring(6, attributeName.Length - 6);
 
1532
          return true;
 
1533
        }
 
1534
      }
 
1535
      prefix = null;
 
1536
      return false;
 
1537
    }
 
1538
 
 
1539
    private IEnumerable<IXmlNode> ValueAttributes(IEnumerable<IXmlNode> c)
 
1540
    {
 
1541
      return c.Where(a => a.NamespaceUri != JsonNamespaceUri);
 
1542
    }
 
1543
    #endregion
 
1544
 
 
1545
    /// <summary>
 
1546
    /// Determines whether this instance can convert the specified value type.
 
1547
    /// </summary>
 
1548
    /// <param name="valueType">Type of the value.</param>
 
1549
    /// <returns>
 
1550
    ///         <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
 
1551
    /// </returns>
 
1552
    public override bool CanConvert(Type valueType)
 
1553
    {
 
1554
#if !NET20
 
1555
      if (typeof(XObject).IsAssignableFrom(valueType))
 
1556
        return true;
 
1557
#endif
 
1558
#if !(SILVERLIGHT || NETFX_CORE)
 
1559
      if (typeof(XmlNode).IsAssignableFrom(valueType))
 
1560
        return true;
 
1561
#endif
 
1562
 
 
1563
      return false;
 
1564
    }
 
1565
  }
 
1566
}
 
1567
#endif
 
 
b'\\ No newline at end of file'