Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Converters\XmlNodeConverter.cs

Symbol Coverage: 91.54% (411 of 449)

Branch Coverage: 90.23% (240 of 266)

Cyclomatic Complexity Avg: 2.81 Max:26

Code Lines: 534


L V Source
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
27
using System;
28
using System.Collections.Generic;
29
using System.Xml;
30
#if !NET20
31
using System.Xml.Linq;
32
#endif
33
using Newtonsoft.Json.Utilities;
34
using System.Linq;
35

  
36
namespace Newtonsoft.Json.Converters
37
{
38
  #region Wrappers
39
  internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument
40
  {
41
    private XmlDocument _document;
42

  
43
 17
    public XmlDocumentWrapper(XmlDocument document)
44
 17
      : base(document)
45
    {
46
 17
      _document = document;
47
 17
    }
48

  
49
    public IXmlNode CreateComment(string data)
50
    {
51
 1
      return new XmlNodeWrapper(_document.CreateComment(data));
52
 1
    }
53

  
54
    public IXmlNode CreateTextNode(string text)
55
    {
56
 41
      return new XmlNodeWrapper(_document.CreateTextNode(text));
57
 41
    }
58

  
59
    public IXmlNode CreateCDataSection(string data)
60
    {
61
 1
      return new XmlNodeWrapper(_document.CreateCDataSection(data));
62
 1
    }
63

  
64
    public IXmlNode CreateWhitespace(string text)
65
    {
66
 0
      return new XmlNodeWrapper(_document.CreateWhitespace(text));
67
 0
    }
68

  
69
    public IXmlNode CreateSignificantWhitespace(string text)
70
    {
71
 0
      return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text));
72
 0
    }
73

  
74
    public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
75
    {
76
 7
      return new XmlNodeWrapper(_document.CreateXmlDeclaration(version, encoding, standalone));
77
 7
    }
78

  
79
    public IXmlNode CreateProcessingInstruction(string target, string data)
80
    {
81
 0
      return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data));
82
 0
    }
83

  
84
    public IXmlElement CreateElement(string elementName)
85
    {
86
 77
      return new XmlElementWrapper(_document.CreateElement(elementName));
87
 77
    }
88

  
89
    public IXmlElement CreateElement(string qualifiedName, string namespaceURI)
90
    {
91
 10
      return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceURI));
92
 10
    }
93

  
94
    public IXmlNode CreateAttribute(string name, string value)
95
    {
96
 29
      XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name));
97
 29
      attribute.Value = value;
98

  
99
 29
      return attribute;
100
 29
    }
101

  
102
    public IXmlNode CreateAttribute(string qualifiedName, string namespaceURI, string value)
103
    {
104
 8
      XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceURI));
105
 8
      attribute.Value = value;
106

  
107
 8
      return attribute;
108
 8
    }
109

  
110
    public IXmlElement DocumentElement
111
    {
112
      get
113
      {
114
 21
        if (_document.DocumentElement == null)
115
 19
          return null;
116

  
117
 2
        return new XmlElementWrapper(_document.DocumentElement);
118
 21
      }
119
    }
120
  }
121

  
122
  internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement
123
  {
124
    private XmlElement _element;
125

  
126
 509
    public XmlElementWrapper(XmlElement element)
127
 509
      : base(element)
128
    {
129
 509
      _element = element;
130
 509
    }
131

  
132
    public void SetAttributeNode(IXmlNode attribute)
133
    {
134
 37
      XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute;
135

  
136
 37
      _element.SetAttributeNode((XmlAttribute) xmlAttributeWrapper.WrappedNode);
137
 37
    }
138
  }
139

  
140
  internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration
141
  {
142
    private XmlDeclaration _declaration;
143

  
144
 27
    public XmlDeclarationWrapper(XmlDeclaration declaration)
145
 27
      : base(declaration)
146
    {
147
 27
      _declaration = declaration;
148
 27
    }
149

  
150
    public string Version
151
    {
152
 10
      get { return _declaration.Version; }
153
    }
154

  
155
    public string Encoding
156
    {
157
 6
      get { return _declaration.Encoding; }
158
 0
      set { _declaration.Encoding = value; }
159
    }
160

  
161
    public string Standalone
162
    {
163
 9
      get { return _declaration.Standalone; }
164
 0
      set { _declaration.Standalone = value; }
165
    }
166
  }
167

  
168
  internal class XmlNodeWrapper : IXmlNode
169
  {
170
    private readonly XmlNode _node;
171

  
172
 1192
    public XmlNodeWrapper(XmlNode node)
173
    {
174
 1192
      _node = node;
175
 1192
    }
176

  
177
    public object WrappedNode
178
    {
179
 51
      get { return _node; }
180
    }
181

  
182
    public XmlNodeType NodeType
183
    {
184
 439
      get { return _node.NodeType; }
185
    }
186

  
187
    public string Name
188
    {
189
 0
      get { return _node.Name; }
190
    }
191

  
192
    public string LocalName
193
    {
194
 376
      get { return _node.LocalName; }
195
    }
196

  
197
    public IList<IXmlNode> ChildNodes
198
    {
199
 355
      get { return _node.ChildNodes.Cast<XmlNode>().Select(n => WrapNode(n)).ToList(); }
200
    }
201

  
202
    private IXmlNode WrapNode(XmlNode node)
203
    {
204
 981
      switch (node.NodeType)
205
      {
206
        case XmlNodeType.Element:
207
 420
          return new XmlElementWrapper((XmlElement) node);
208
        case XmlNodeType.XmlDeclaration:
209
 27
          return new XmlDeclarationWrapper((XmlDeclaration) node);
210
        default:
211
 534
          return new XmlNodeWrapper(node);
212
      }
213
 981
    }
214

  
215
    public IList<IXmlNode> Attributes
216
    {
217
      get
218
      {
219
 388
        if (_node.Attributes == null)
220
 15
          return null;
221

  
222
 373
        return _node.Attributes.Cast<XmlAttribute>().Select(a => WrapNode(a)).ToList();
223
 388
      }
224
    }
225

  
226
    public IXmlNode ParentNode
227
    {
228
      get
229
      {
230
 22
        XmlNode node = (_node is XmlAttribute)
231
 22
                         ? ((XmlAttribute) _node).OwnerElement
232
 22
                         : _node.ParentNode;
233
        
234
 22
        if (node == null)
235
 18
          return null;
236

  
237
 4
        return WrapNode(node);
238
 22
      }
239
    }
240

  
241
    public string Value
242
    {
243
 105
      get { return _node.Value; }
244
 37
      set { _node.Value = value; }
245
    }
246

  
247
    public IXmlNode AppendChild(IXmlNode newChild)
248
    {
249
 137
      XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper) newChild;
250
 137
      _node.AppendChild(xmlNodeWrapper._node);
251

  
252
 137
      return newChild;
253
 137
    }
254

  
255
    public string Prefix
256
    {
257
 0
      get { return _node.Prefix; }
258
    }
259

  
260
    public string NamespaceURI
261
    {
262
 590
      get { return _node.NamespaceURI; }
263
    }
264
  }
265

  
266
  internal interface IXmlDocument : IXmlNode
267
  {
268
    IXmlNode CreateComment(string text);
269
    IXmlNode CreateTextNode(string text);
270
    IXmlNode CreateCDataSection(string data);
271
    IXmlNode CreateWhitespace(string text);
272
    IXmlNode CreateSignificantWhitespace(string text);
273
    IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone);
274
    IXmlNode CreateProcessingInstruction(string target, string data);
275
    IXmlElement CreateElement(string elementName);
276
    IXmlElement CreateElement(string qualifiedName, string namespaceURI);
277
    IXmlNode CreateAttribute(string name, string value);
278
    IXmlNode CreateAttribute(string qualifiedName, string namespaceURI, string value);
279

  
280
    IXmlElement DocumentElement { get; }
281
  }
282

  
283
  internal interface IXmlDeclaration : IXmlNode
284
  {
285
    string Version { get; }
286
    string Encoding { get; set; }
287
    string Standalone { get; set; }
288
  }
289

  
290
  internal interface IXmlElement : IXmlNode
291
  {
292
    void SetAttributeNode(IXmlNode attribute);
293
  }
294

  
295
  internal interface IXmlNode
296
  {
297
    XmlNodeType NodeType { get; }
298
    string LocalName { get; }
299
    IList<IXmlNode> ChildNodes { get; }
300
    IList<IXmlNode> Attributes { get; }
301
    IXmlNode ParentNode { get; }
302
    string Value { get; set; }
303
    IXmlNode AppendChild(IXmlNode newChild);
304
    string NamespaceURI { get; }
305
    object WrappedNode { get; }
306
  }
307

  
308
  #if !NET20
309
  internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration
310
  {
311
    internal readonly XDeclaration _declaration;
312

  
313
 34
    public XDeclarationWrapper(XDeclaration declaration)
314
 34
      : base(null)
315
    {
316
 34
      _declaration = declaration;
317
 34
    }
318

  
319
    public override XmlNodeType NodeType
320
    {
321
 15
      get { return XmlNodeType.XmlDeclaration; }
322
    }
323

  
324
    public string Version
325
    {
326
 10
      get { return _declaration.Version; }
327
    }
328

  
329
    public string Encoding
330
    {
331
 6
      get { return _declaration.Encoding; }
332
 0
      set { _declaration.Encoding = value; }
333
    }
334

  
335
    public string Standalone
336
    {
337
 9
      get { return _declaration.Standalone; }
338
 0
      set { _declaration.Standalone = value; }
339
    }
340
  }
341

  
342
  internal class XDocumentWrapper : XContainerWrapper, IXmlDocument
343
  {
344
    private XDocument Document
345
    {
346
 108
      get { return (XDocument)WrappedNode; }
347
    }
348

  
349
 29
    public XDocumentWrapper(XDocument document)
350
 29
      : base(document)
351
    {
352
 29
    }
353

  
354
    public override IList<IXmlNode> ChildNodes
355
    {
356
      get
357
      {
358
 51
        IList<IXmlNode> childNodes = base.ChildNodes;
359

  
360
 51
        if (Document.Declaration != null)
361
 27
          childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration));
362

  
363
 51
        return childNodes;
364
 51
      }
365
    }
366

  
367
    public IXmlNode CreateComment(string text)
368
    {
369
 1
      return new XObjectWrapper(new XComment(text));
370
 1
    }
371

  
372
    public IXmlNode CreateTextNode(string text)
373
    {
374
 41
      return new XObjectWrapper(new XText(text));
375
 41
    }
376

  
377
    public IXmlNode CreateCDataSection(string data)
378
    {
379
 1
      return new XObjectWrapper(new XCData(data));
380
 1
    }
381

  
382
    public IXmlNode CreateWhitespace(string text)
383
    {
384
 0
      return new XObjectWrapper(new XText(text));
385
 0
    }
386

  
387
    public IXmlNode CreateSignificantWhitespace(string text)
388
    {
389
 0
      return new XObjectWrapper(new XText(text));
390
 0
    }
391

  
392
    public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
393
    {
394
 7
      return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone));
395
 7
    }
396

  
397
    public IXmlNode CreateProcessingInstruction(string target, string data)
398
    {
399
 0
      return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data));
400
 0
    }
401

  
402
    public IXmlElement CreateElement(string elementName)
403
    {
404
 77
      return new XElementWrapper(new XElement(elementName));
405
 77
    }
406

  
407
    public IXmlElement CreateElement(string qualifiedName, string namespaceURI)
408
    {
409
 10
      string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
410
 10
      return new XElementWrapper(new XElement(XName.Get(localName, namespaceURI)));
411
 10
    }
412

  
413
    public IXmlNode CreateAttribute(string name, string value)
414
    {
415
 29
      return new XAttributeWrapper(new XAttribute(name, value));
416
 29
    }
417

  
418
    public IXmlNode CreateAttribute(string qualifiedName, string namespaceURI, string value)
419
    {
420
 10
      string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
421
 10
      return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceURI), value));
422
 10
    }
423

  
424
    public IXmlElement DocumentElement
425
    {
426
      get
427
      {
428
 21
        if (Document.Root == null)
429
 19
          return null;
430

  
431
 2
        return new XElementWrapper(Document.Root);
432
 21
      }
433
    }
434

  
435
    public override IXmlNode AppendChild(IXmlNode newChild)
436
    {
437
 23
      XDeclarationWrapper declarationWrapper = newChild as XDeclarationWrapper;
438
 23
      if (declarationWrapper != null)
439
      {
440
 7
        Document.Declaration = declarationWrapper._declaration;
441
 7
        return declarationWrapper;
442
      }
443
      else
444
      {
445
 16
        return base.AppendChild(newChild);
446
      }
447
 23
    }
448
  }
449

  
450
  internal class XTextWrapper : XObjectWrapper
451
  {
452
    private XText Text
453
    {
454
 32
      get { return (XText)WrappedNode; }
455
    }
456

  
457
 107
    public XTextWrapper(XText text)
458
 107
      : base(text)
459
    {
460
 107
    }
461

  
462
    public override string Value
463
    {
464
 32
      get { return Text.Value; }
465
 0
      set { Text.Value = value; }
466
    }
467

  
468
    public override IXmlNode ParentNode
469
    {
470
      get
471
      {
472
 0
        if (Text.Parent == null)
473
 0
          return null;
474
        
475
 0
        return XContainerWrapper.WrapNode(Text.Parent);
476
 0
      }
477
    }
478
  }
479

  
480
  internal class XCommentWrapper : XObjectWrapper
481
  {
482
    private XComment Text
483
    {
484
 1
      get { return (XComment)WrappedNode; }
485
    }
486

  
487
 6
    public XCommentWrapper(XComment text)
488
 6
      : base(text)
489
    {
490
 6
    }
491

  
492
    public override string Value
493
    {
494
 1
      get { return Text.Value; }
495
 0
      set { Text.Value = value; }
496
    }
497

  
498
    public override IXmlNode ParentNode
499
    {
500
      get
501
      {
502
 0
        if (Text.Parent == null)
503
 0
          return null;
504

  
505
 0
        return XContainerWrapper.WrapNode(Text.Parent);
506
 0
      }
507
    }
508
  }
509

  
510
  internal class XProcessingInstructionWrapper : XObjectWrapper
511
  {
512
    private XProcessingInstruction ProcessingInstruction
513
    {
514
 3
      get { return (XProcessingInstruction)WrappedNode; }
515
    }
516

  
517
 7
    public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction)
518
 7
      : base(processingInstruction)
519
    {
520
 7
    }
521

  
522
    public override string LocalName
523
    {
524
 2
      get { return ProcessingInstruction.Target; }
525
    }
526

  
527
    public override string Value
528
    {
529
 1
      get { return ProcessingInstruction.Data; }
530
 0
      set { ProcessingInstruction.Data = value; }
531
    }
532
  }
533

  
534
  internal class XContainerWrapper : XObjectWrapper
535
  {
536
    private XContainer Container
537
    {
538
 489
      get { return (XContainer)WrappedNode; }
539
    }
540

  
541
 529
    public XContainerWrapper(XContainer container)
542
 529
      : base(container)
543
    {
544
 529
    }
545

  
546
    public override IList<IXmlNode> ChildNodes
547
    {
548
 342
      get { return Container.Nodes().Select(n => WrapNode(n)).ToList(); }
549
    }
550

  
551
    public override IXmlNode ParentNode
552
    {
553
      get
554
      {
555
 16
        if (Container.Parent == null)
556
 15
          return null;
557
        
558
 1
        return WrapNode(Container.Parent);
559
 16
      }
560
    }
561

  
562
    internal static IXmlNode WrapNode(XObject node)
563
    {
564
 545
      if (node is XDocument)
565
 13
        return new XDocumentWrapper((XDocument)node);
566
 532
      else if (node is XElement)
567
 411
        return new XElementWrapper((XElement)node);
568
 121
      else if (node is XContainer)
569
 0
        return new XContainerWrapper((XContainer)node);
570
 121
      else if (node is XProcessingInstruction)
571
 7
        return new XProcessingInstructionWrapper((XProcessingInstruction)node);
572
 114
      else if (node is XText)
573
 107
        return new XTextWrapper((XText)node);
574
 7
      else if (node is XComment)
575
 6
        return new XCommentWrapper((XComment)node);
576
 1
      else if (node is XAttribute)
577
 1
        return new XAttributeWrapper((XAttribute) node);
578
      else
579
 0
        return new XObjectWrapper(node);
580
 545
    }
581

  
582
    public override IXmlNode AppendChild(IXmlNode newChild)
583
    {
584
 130
      Container.Add(newChild.WrappedNode);
585
 130
      return newChild;
586
 130
    }
587
  }
588

  
589
  internal class XObjectWrapper : IXmlNode
590
  {
591
    private readonly XObject _xmlObject;
592

  
593
 1151
    public XObjectWrapper(XObject xmlObject)
594
    {
595
 1151
      _xmlObject = xmlObject;
596
 1151
    }
597

  
598
    public object WrappedNode
599
    {
600
 2190
      get { return _xmlObject; }
601
    }
602

  
603
    public virtual XmlNodeType NodeType
604
    {
605
 406
      get { return _xmlObject.NodeType; }
606
    }
607

  
608
    public virtual string LocalName
609
    {
610
 0
      get { return null; }
611
    }
612

  
613
    public virtual IList<IXmlNode> ChildNodes
614
    {
615
 0
      get { return new List<IXmlNode>(); }
616
    }
617

  
618
    public virtual IList<IXmlNode> Attributes
619
    {
620
 14
      get { return null; }
621
    }
622

  
623
    public virtual IXmlNode ParentNode
624
    {
625
 0
      get { return null; }
626
    }
627

  
628
    public virtual string Value
629
    {
630
 0
      get { return null; }
631
 0
      set { throw new InvalidOperationException(); }
632
    }
633

  
634
    public virtual IXmlNode AppendChild(IXmlNode newChild)
635
    {
636
 0
      throw new InvalidOperationException();
637
    }
638

  
639
    public virtual string NamespaceURI
640
    {
641
 18
      get { return null; }
642
    }
643
  }
644

  
645
  internal class XAttributeWrapper : XObjectWrapper
646
  {
647
    private XAttribute Attribute
648
    {
649
 515
      get { return (XAttribute)WrappedNode; }
650
    }
651

  
652
 425
    public XAttributeWrapper(XAttribute attribute)
653
 425
      : base(attribute)
654
    {
655
 425
    }
656

  
657
    public override string Value
658
    {
659
 61
      get { return Attribute.Value; }
660
 0
      set { Attribute.Value = value; }
661
    }
662

  
663
    public override string LocalName
664
    {
665
 130
      get { return Attribute.Name.LocalName; }
666
    }
667

  
668
    public override string NamespaceURI
669
    {
670
 322
      get { return Attribute.Name.NamespaceName; }
671
    }
672

  
673
    public override IXmlNode ParentNode
674
    {
675
      get
676
      {
677
 1
        if (Attribute.Parent == null)
678
 0
          return null;
679

  
680
 1
        return XContainerWrapper.WrapNode(Attribute.Parent);
681
 1
      }
682
    }
683
  }
684

  
685
  internal class XElementWrapper : XContainerWrapper, IXmlElement
686
  {
687
    private XElement Element
688
    {
689
 858
      get { return (XElement) WrappedNode; }
690
    }
691

  
692
 500
    public XElementWrapper(XElement element)
693
 500
      : base(element)
694
    {
695
 500
    }
696

  
697
    public void SetAttributeNode(IXmlNode attribute)
698
    {
699
 39
      XObjectWrapper wrapper = (XObjectWrapper)attribute;
700
 39
      Element.Add(wrapper.WrappedNode);
701
 39
    }
702

  
703
    public override IList<IXmlNode> Attributes
704
    {
705
 367
      get { return Element.Attributes().Select(a => new XAttributeWrapper(a)).Cast<IXmlNode>().ToList(); }
706
    }
707

  
708
    public override string Value
709
    {
710
 0
      get { return Element.Value; }
711
 0
      set { Element.Value = value; }
712
    }
713

  
714
    public override string LocalName
715
    {
716
 226
      get { return Element.Name.LocalName; }
717
    }
718

  
719
    public override string NamespaceURI
720
    {
721
 226
      get { return Element.Name.NamespaceName; }
722
    }
723
  }
724
#endif
725
  #endregion
726

  
727
  /// <summary>
728
  /// Converts an <see cref="XmlNode"/> to and from JSON.
729
  /// </summary>
730
  public class XmlNodeConverter : JsonConverter
731
  {
732
    private const string TextName = "#text";
733
    private const string CommentName = "#comment";
734
    private const string CDataName = "#cdata-section";
735
    private const string WhitespaceName = "#whitespace";
736
    private const string SignificantWhitespaceName = "#significant-whitespace";
737
    private const string DeclarationName = "?xml";
738
    private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
739

  
740
    /// <summary>
741
    /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
742
    /// </summary>
743
    /// <value>The name of the deserialize root element.</value>
744
    public string DeserializeRootElementName { get; set; }
745

  
746
    #region Writing
747
    /// <summary>
748
    /// Writes the JSON representation of the object.
749
    /// </summary>
750
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
751
    /// <param name="serializer">The calling serializer.</param>
752
    /// <param name="value">The value.</param>
753
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
754
    {
755
      IXmlNode node;
756

  
757
 33
      if (value is XmlNode)
758
 18
        node = new XmlNodeWrapper((XmlNode)value);
759
#if !NET20
760
 15
      else if (value is XObject)
761
 15
        node = XContainerWrapper.WrapNode((XObject)value);
762
#endif
763
      else
764
 0
        throw new ArgumentException("Value must be an XmlNode", "value");
765

  
766
 33
      XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
767
 33
      PushParentNamespaces(node, manager);
768

  
769
 33
      writer.WriteStartObject();
770
 33
      SerializeNode(writer, node, manager, true);
771
 33
      writer.WriteEndObject();
772
 33
    }
773

  
774
    private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
775
    {
776
 33
      List<IXmlNode> parentElements = null;
777

  
778
 33
      IXmlNode parent = node;
779
 39
      while ((parent = parent.ParentNode) != null)
780
      {
781
 6
        if (parent.NodeType == XmlNodeType.Element)
782
        {
783
 4
          if (parentElements == null)
784
 2
            parentElements = new List<IXmlNode>();
785

  
786
 4
          parentElements.Add(parent);
787
        }
788
      }
789

  
790
 33
      if (parentElements != null)
791
      {
792
 2
        parentElements.Reverse();
793

  
794
 2
        foreach (IXmlNode parentElement in parentElements)
795
        {
796
 4
          manager.PushScope();
797
 4
          foreach (IXmlNode attribute in parentElement.Attributes)
798
          {
799
 12
            if (attribute.NamespaceURI == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns")
800
 4
              manager.AddNamespace(attribute.LocalName, attribute.Value);
801
          }
802
        }
803
      }
804
 33
    }
805

  
806
    private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
807
    {
808
 316
      string prefix = (node.NamespaceURI == null || (node.LocalName == "xmlns" && node.NamespaceURI == "http://www.w3.org/2000/xmlns/"))
809
 316
                        ? null
810
 316
                        : manager.LookupPrefix(node.NamespaceURI);
811

  
812
 316
      if (!string.IsNullOrEmpty(prefix))
813
 48
        return prefix + ":" + node.LocalName;
814
      else
815
 268
        return node.LocalName;
816
 316
    }
817

  
818
    private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager)
819
    {
820
 373
      switch (node.NodeType)
821
      {
822
        case XmlNodeType.Attribute:
823
 87
          if (node.NamespaceURI == JsonNamespaceUri)
824
 6
            return "$" + node.LocalName;
825
          else
826
 81
            return "@" + ResolveFullName(node, manager);
827
        case XmlNodeType.CDATA:
828
 7
          return CDataName;
829
        case XmlNodeType.Comment:
830
 2
          return CommentName;
831
        case XmlNodeType.Element:
832
 228
          return ResolveFullName(node, manager);
833
        case XmlNodeType.ProcessingInstruction:
834
 7
          return "?" + ResolveFullName(node, manager);
835
        case XmlNodeType.XmlDeclaration:
836
 20
          return DeclarationName;
837
        case XmlNodeType.SignificantWhitespace:
838
 0
          return SignificantWhitespaceName;
839
        case XmlNodeType.Text:
840
 22
          return TextName;
841
        case XmlNodeType.Whitespace:
842
 0
          return WhitespaceName;
843
        default:
844
 0
          throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
845
      }
846
 373
    }
847

  
848
    private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager)
849
    {
850
      // group nodes together by name
851
 105
      Dictionary<string, List<IXmlNode>> nodesGroupedByName = new Dictionary<string, List<IXmlNode>>();
852

  
853
 105
      for (int i = 0; i < node.ChildNodes.Count; i++)
854
      {
855
 161
        IXmlNode childNode = node.ChildNodes[i];
856
 161
        string nodeName = GetPropertyName(childNode, manager);
857

  
858
        List<IXmlNode> nodes;
859
 161
        if (!nodesGroupedByName.TryGetValue(nodeName, out nodes))
860
        {
861
 142
          nodes = new List<IXmlNode>();
862
 142
          nodesGroupedByName.Add(nodeName, nodes);
863
        }
864

  
865
 161
        nodes.Add(childNode);
866
      }
867

  
868
      // loop through grouped nodes. write single name instances as normal,
869
      // write multiple names together in an array
870
 105
      foreach (KeyValuePair<string, List<IXmlNode>> nodeNameGroup in nodesGroupedByName)
871
      {
872
 142
        List<IXmlNode> groupedNodes = nodeNameGroup.Value;
873
        bool writeArray;
874

  
875
 142
        if (groupedNodes.Count == 1)
876
        {
877
 125
          IXmlNode singleNode = groupedNodes[0];
878
 125
          IXmlNode jsonArrayAttribute = (singleNode.Attributes != null)
879
 52
            ? singleNode.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceURI == JsonNamespaceUri)
880
 125
            : null;
881
 125
          if (jsonArrayAttribute != null)
882
 4
            writeArray = XmlConvert.ToBoolean(jsonArrayAttribute.Value);
883
          else
884
 121
            writeArray = false;
885
        }
886
        else
887
        {
888
 17
          writeArray = true;
889
        }
890

  
891
 142
        if (!writeArray)
892
        {
893
 123
          SerializeNode(writer, groupedNodes[0], manager, true);
894
        }
895
        else
896
        {
897
 19
          string elementNames = nodeNameGroup.Key;
898
 19
          writer.WritePropertyName(elementNames);
899
 19
          writer.WriteStartArray();
900

  
901
 19
          for (int i = 0; i < groupedNodes.Count; i++)
902
          {
903
 38
            SerializeNode(writer, groupedNodes[i], manager, false);
904
          }
905

  
906
 19
          writer.WriteEndArray();
907
        }
908
      }
909
 105
    }
910

  
911
    private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
912
    {
913
 287
      switch (node.NodeType)
914
      {
915
        case XmlNodeType.Document:
916
        case XmlNodeType.DocumentFragment:
917
 27
          SerializeGroupedNodes(writer, node, manager);
918
 27
          break;
919
        case XmlNodeType.Element:
920
 101
          foreach (IXmlNode attribute in node.Attributes)
921
          {
922
 101
            if (attribute.NamespaceURI == "http://www.w3.org/2000/xmlns/")
923
            {
924
 16
              string prefix = (attribute.LocalName != "xmlns")
925
 16
                                ? attribute.LocalName
926
 16
                                : string.Empty;
927

  
928
 16
              manager.AddNamespace(prefix, attribute.Value);
929
            }
930
          }
931

  
932
 134
          if (writePropertyName)
933
 96
            writer.WritePropertyName(GetPropertyName(node, manager));
934

  
935
 134
          if (ValueAttributes(node.Attributes).Count() == 0 && node.ChildNodes.Count == 1
936
 134
                  && node.ChildNodes[0].NodeType == XmlNodeType.Text)
937
          {
938
            // write elements with a single text child as a name value pair
939
 52
            writer.WriteValue(node.ChildNodes[0].Value);
940
          }
941
 82
          else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
942
          {
943
            // empty element
944
 4
            writer.WriteNull();
945
          }
946
          else
947
          {
948
 78
            writer.WriteStartObject();
949

  
950
 78
            for (int i = 0; i < node.Attributes.Count; i++)
951
            {
952
 93
              SerializeNode(writer, node.Attributes[i], manager, true);
953
            }
954

  
955
 78
            SerializeGroupedNodes(writer, node, manager);
956

  
957
 78
            writer.WriteEndObject();
958
          }
959

  
960
 134
          break;
961
        case XmlNodeType.Comment:
962
 2
          if (writePropertyName)
963
 2
            writer.WriteComment(node.Value);
964
 2
          break;
965
        case XmlNodeType.Attribute:
966
        case XmlNodeType.Text:
967
        case XmlNodeType.CDATA:
968
        case XmlNodeType.ProcessingInstruction:
969
        case XmlNodeType.Whitespace:
970
        case XmlNodeType.SignificantWhitespace:
971
 114
          if (node.NamespaceURI == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
972
 8
            return;
973

  
974
 106
          if (node.NamespaceURI == JsonNamespaceUri)
975
          {
976
 6
            if (node.LocalName == "Array")
977
 0
              return;
978
          }
979

  
980
 106
          if (writePropertyName)
981
 106
            writer.WritePropertyName(GetPropertyName(node, manager));
982
 106
          writer.WriteValue(node.Value);
983
 106
          break;
984
        case XmlNodeType.XmlDeclaration:
985
 10
          IXmlDeclaration declaration = (IXmlDeclaration)node;
986
 10
          writer.WritePropertyName(GetPropertyName(node, manager));
987
 10
          writer.WriteStartObject();
988

  
989
 10
          if (!string.IsNullOrEmpty(declaration.Version))
990
          {
991
 10
            writer.WritePropertyName("@version");
992
 10
            writer.WriteValue(declaration.Version);
993
          }
994
 10
          if (!string.IsNullOrEmpty(declaration.Encoding))
995
          {
996
 2
            writer.WritePropertyName("@encoding");
997
 2
            writer.WriteValue(declaration.Encoding);
998
          }
999
 10
          if (!string.IsNullOrEmpty(declaration.Standalone))
1000
          {
1001
 8
            writer.WritePropertyName("@standalone");
1002
 8
            writer.WriteValue(declaration.Standalone);
1003
          }
1004

  
1005
 10
          writer.WriteEndObject();
1006
 10
          break;
1007
        default:
1008
 0
          throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
1009
      }
1010
 287
    }
1011
    #endregion
1012

  
1013
    #region Reading
1014
    /// <summary>
1015
    /// Reads the JSON representation of the object.
1016
    /// </summary>
1017
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
1018
    /// <param name="objectType">Type of the object.</param>
1019
    /// <param name="existingValue">The existing value of object being read.</param>
1020
    /// <param name="serializer">The calling serializer.</param>
1021
    /// <returns>The object value.</returns>
1022
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
1023
    {
1024
 33
      XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
1025
      IXmlDocument document;
1026
      IXmlNode rootNode;
1027

  
1028
 33
      if (typeof (XmlNode).IsAssignableFrom(objectType))
1029
      {
1030
 17
        if (objectType != typeof (XmlDocument))
1031
 0
          throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
1032

  
1033
 17
        XmlDocument d = new XmlDocument();
1034
 17
        document = new XmlDocumentWrapper(d);
1035
 17
        rootNode = document;
1036
      }
1037
#if !NET20
1038
 16
      else if (typeof(XObject).IsAssignableFrom(objectType))
1039
      {
1040
 16
        if (objectType != typeof (XDocument) && objectType != typeof (XElement))
1041
 0
          throw new JsonSerializationException("XmlNodeConverter only supports deserializing XDocument or XElement.");
1042

  
1043
 16
        XDocument d = new XDocument();
1044
 16
        document = new XDocumentWrapper(d);
1045
 16
        rootNode = document;
1046
      }
1047
#endif
1048
      else
1049
      {
1050
 0
        throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
1051
      }
1052

  
1053
 33
      if (reader.TokenType != JsonToken.StartObject)
1054
 1
        throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
1055

  
1056
 32
      if (!string.IsNullOrEmpty(DeserializeRootElementName))
1057
      {
1058
        //rootNode = document.CreateElement(DeserializeRootElementName);
1059
        //document.AppendChild(rootNode);
1060
 8
        ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
1061
      }
1062
      else
1063
      {
1064
 24
        reader.Read();
1065
 24
        DeserializeNode(reader, document, manager, rootNode);
1066
      }
1067

  
1068
#if !NET20
1069
 29
      if (objectType == typeof(XElement))
1070
      {
1071
 1
        XElement element = (XElement)document.DocumentElement.WrappedNode;
1072
 1
        element.Remove();
1073

  
1074
 1
        return element;
1075
      }
1076
#endif
1077

  
1078
 28
      return document.WrappedNode;
1079
 29
    }
1080

  
1081
    private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode)
1082
    {
1083
 187
      switch (propertyName)
1084
      {
1085
        case TextName:
1086
 5
          currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
1087
 5
          break;
1088
        case CDataName:
1089
 2
          currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
1090
 2
          break;
1091
        case WhitespaceName:
1092
 0
          currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
1093
 0
          break;
1094
        case SignificantWhitespaceName:
1095
 0
          currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
1096
 0
          break;
1097
        default:
1098
          // processing instructions and the xml declaration start with ?
1099
 180
          if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
1100
          {
1101
 14
            CreateInstruction(reader, document, currentNode, propertyName);
1102
          }
1103
          else
1104
          {
1105
 166
            if (reader.TokenType == JsonToken.StartArray)
1106
            {
1107
 16
              ReadArrayElements(reader, document, propertyName, currentNode, manager);
1108
 16
              return;
1109
            }
1110

  
1111
            // have to wait until attributes have been parsed before creating element
1112
            // attributes may contain namespace info used by the element
1113
 150
            ReadElement(reader, document, currentNode, propertyName, manager);
1114
          }
1115
 164
          break;
1116
      }
1117
 187
    }
1118

  
1119
    private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
1120
    {
1121
 158
      Dictionary<string, string> attributeNameValues = ReadAttributeElements(reader, manager);
1122

  
1123
 158
      string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
1124

  
1125
 158
      IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
1126

  
1127
 158
      currentNode.AppendChild(element);
1128

  
1129
      // add attributes to newly created element
1130
 76
      foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
1131
      {
1132
 76
        string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
1133

  
1134
 76
        IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
1135
 76
                               ? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
1136
 76
                               : document.CreateAttribute(nameValue.Key, nameValue.Value);
1137

  
1138
 76
        element.SetAttributeNode(attribute);
1139
      }
1140

  
1141
 158
      if (reader.TokenType == JsonToken.String)
1142
      {
1143
 46
        element.AppendChild(document.CreateTextNode(reader.Value.ToString()));
1144
      }
1145
 112
      else if (reader.TokenType == JsonToken.Integer)
1146
      {
1147
 25
        element.AppendChild(document.CreateTextNode(XmlConvert.ToString((long)reader.Value)));
1148
      }
1149
 87
      else if (reader.TokenType == JsonToken.Float)
1150
      {
1151
 2
        element.AppendChild(document.CreateTextNode(XmlConvert.ToString((double)reader.Value)));
1152
      }
1153
 85
      else if (reader.TokenType == JsonToken.Boolean)
1154
      {
1155
 2
        element.AppendChild(document.CreateTextNode(XmlConvert.ToString((bool)reader.Value)));
1156
      }
1157
 83
      else if (reader.TokenType == JsonToken.Date)
1158
      {
1159
 2
        DateTime d = (DateTime)reader.Value;
1160
 2
        element.AppendChild(document.CreateTextNode(XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind))));
1161
      }
1162
 81
      else if (reader.TokenType == JsonToken.Null)
1163
      {
1164
        // empty element. do nothing
1165
      }
1166
      else
1167
      {
1168
        // finished element will have no children to deserialize
1169
 77
        if (reader.TokenType != JsonToken.EndObject)
1170
        {
1171
 69
          manager.PushScope();
1172

  
1173
 69
          DeserializeNode(reader, document, manager, element);
1174

  
1175
 69
          manager.PopScope();
1176
        }
1177
      }
1178
 158
    }
1179

  
1180
    private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
1181
    {
1182
 16
      string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
1183

  
1184
 16
      IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
1185

  
1186
 16
      currentNode.AppendChild(nestedArrayElement);
1187

  
1188
 48
      while (reader.Read() && reader.TokenType != JsonToken.EndArray)
1189
      {
1190
 32
        DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
1191
      }
1192
 16
    }
1193

  
1194
    private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
1195
    {
1196
 158
      Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
1197
 158
      bool finishedAttributes = false;
1198
 158
      bool finishedElement = false;
1199

  
1200
      // a string token means the element only has a single text child
1201
 158
      if (reader.TokenType != JsonToken.String
1202
 158
          && reader.TokenType != JsonToken.Null
1203
 158
          && reader.TokenType != JsonToken.Boolean
1204
 158
          && reader.TokenType != JsonToken.Integer
1205
 158
          && reader.TokenType != JsonToken.Float
1206
 158
          && reader.TokenType != JsonToken.Date
1207
 158
          && reader.TokenType != JsonToken.StartConstructor)
1208
      {
1209
        // read properties until first non-attribute is encountered
1210
 224
        while (!finishedAttributes && !finishedElement && reader.Read())
1211
        {
1212
 149
          switch (reader.TokenType)
1213
          {
1214
            case JsonToken.PropertyName:
1215
 141
              string attributeName = reader.Value.ToString();
1216
              string attributeValue;
1217
 141
              char firstChar = attributeName[0];
1218

  
1219
 141
              switch (firstChar)
1220
              {
1221
                case '@':
1222
 68
                  attributeName = attributeName.Substring(1);
1223
 68
                  reader.Read();
1224
 68
                  attributeValue = reader.Value.ToString();
1225
 68
                  attributeNameValues.Add(attributeName, attributeValue);
1226

  
1227
                  string namespacePrefix;
1228
 68
                  if (IsNamespaceAttribute(attributeName, out namespacePrefix))
1229
                  {
1230
 7
                    manager.AddNamespace(namespacePrefix, attributeValue);
1231
                  }
1232
 68
                  break;
1233
                case '$':
1234
 6
                  attributeName = attributeName.Substring(1);
1235
 6
                  reader.Read();
1236
 6
                  attributeValue = reader.Value.ToString();
1237

  
1238
                  // check that JsonNamespaceUri is in scope
1239
                  // if it isn't then add it to document and namespace manager
1240
 6
                  string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri);
1241
 6
                  if (jsonPrefix == null)
1242
                  {
1243
                    // ensure that the prefix used is free
1244
 2
                    int? i = null;
1245
 2
                    while (manager.LookupNamespace("json" + i) != null)
1246
                    {
1247
 0
                      i = i.GetValueOrDefault() + 1;
1248
                    }
1249
 2
                    jsonPrefix = "json" + i;
1250

  
1251
 2
                    attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri);
1252
 2
                    manager.AddNamespace(jsonPrefix, JsonNamespaceUri);
1253
                  }
1254

  
1255
 6
                  attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue);
1256
 6
                  break;
1257
                default:
1258
 67
                  finishedAttributes = true;
1259
 67
                  break;
1260
              }
1261
 141
              break;
1262
            case JsonToken.EndObject:
1263
 8
              finishedElement = true;
1264
 8
              break;
1265
            default:
1266
 0
              throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
1267
          }
1268
        }
1269
      }
1270

  
1271
 158
      return attributeNameValues;
1272
 158
    }
1273

  
1274
    private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
1275
    {
1276
 14
      if (propertyName == DeclarationName)
1277
      {
1278
 14
        string version = null;
1279
 14
        string encoding = null;
1280
 14
        string standalone = null;
1281
 42
        while (reader.Read() && reader.TokenType != JsonToken.EndObject)
1282
        {
1283
 28
          switch (reader.Value.ToString())
1284
          {
1285
            case "@version":
1286
 14
              reader.Read();
1287
 14
              version = reader.Value.ToString();
1288
 14
              break;
1289
            case "@encoding":
1290
 2
              reader.Read();
1291
 2
              encoding = reader.Value.ToString();
1292
 2
              break;
1293
            case "@standalone":
1294
 12
              reader.Read();
1295
 12
              standalone = reader.Value.ToString();
1296
 12
              break;
1297
            default:
1298
 0
              throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
1299
          }
1300
        }
1301

  
1302
 14
        IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
1303
 14
        currentNode.AppendChild(declaration);
1304
      }
1305
      else
1306
      {
1307
 0
        IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
1308
 0
        currentNode.AppendChild(instruction);
1309
      }
1310
 14
    }
1311

  
1312
    private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
1313
    {
1314
 174
      return (!string.IsNullOrEmpty(elementPrefix))
1315
 174
               ? document.CreateElement(elementName, manager.LookupNamespace(elementPrefix))
1316
 174
               : document.CreateElement(elementName);
1317
 174
    }
1318

  
1319
    private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
1320
    {
1321
      do
1322
      {
1323
 226
        switch (reader.TokenType)
1324
        {
1325
          case JsonToken.PropertyName:
1326
 134
            if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
1327
 3
              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.");
1328

  
1329
 131
            string propertyName = reader.Value.ToString();
1330
 131
            reader.Read();
1331

  
1332
 131
            if (reader.TokenType == JsonToken.StartArray)
1333
            {
1334
 52
              while (reader.Read() && reader.TokenType != JsonToken.EndArray)
1335
              {
1336
 36
                DeserializeValue(reader, document, manager, propertyName, currentNode);
1337
              }
1338
            }
1339
            else
1340
            {
1341
 115
              DeserializeValue(reader, document, manager, propertyName, currentNode);
1342
            }
1343
 131
            break;
1344
          case JsonToken.StartConstructor:
1345
 2
            string constructorName = reader.Value.ToString();
1346

  
1347
 6
            while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
1348
            {
1349
 4
              DeserializeValue(reader, document, manager, constructorName, currentNode);
1350
            }
1351
 2
            break;
1352
          case JsonToken.Comment:
1353
 2
            currentNode.AppendChild(document.CreateComment((string)reader.Value));
1354
 2
            break;
1355
          case JsonToken.EndObject:
1356
          case JsonToken.EndArray:
1357
 88
            return;
1358
          default:
1359
 0
            throw new JsonSerializationException("Unexpected JsonToken when deserializing node: " + reader.TokenType);
1360
        }
1361
 135
      } while (reader.TokenType == JsonToken.PropertyName || reader.Read());
1362
      // don't read if current token is a property. token was already read when parsing element attributes
1363
 90
    }
1364

  
1365
    /// <summary>
1366
    /// Checks if the attributeName is a namespace attribute.
1367
    /// </summary>
1368
    /// <param name="attributeName">Attribute name to test.</param>
1369
    /// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
1370
    /// <returns>True if attribute name is for a namespace attribute, otherwise false.</returns>
1371
    private bool IsNamespaceAttribute(string attributeName, out string prefix)
1372
    {
1373
 68
      if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
1374
      {
1375
 7
        if (attributeName.Length == 5)
1376
        {
1377
 2
          prefix = string.Empty;
1378
 2
          return true;
1379
        }
1380
 5
        else if (attributeName[5] == ':')
1381
        {
1382
 5
          prefix = attributeName.Substring(6, attributeName.Length - 6);
1383
 5
          return true;
1384
        }
1385
      }
1386
 61
      prefix = null;
1387
 61
      return false;
1388
 68
    }
1389

  
1390
    private IEnumerable<IXmlNode> ValueAttributes(IEnumerable<IXmlNode> c)
1391
    {
1392
 101
      return c.Where(a => a.NamespaceURI != JsonNamespaceUri);
1393
 134
    }
1394
    #endregion
1395

  
1396
    /// <summary>
1397
    /// Determines whether this instance can convert the specified value type.
1398
    /// </summary>
1399
    /// <param name="valueType">Type of the value.</param>
1400
    /// <returns>
1401
    /// 	<c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
1402
    /// </returns>
1403
    public override bool CanConvert(Type valueType)
1404
    {
1405
 343
      if (typeof(XmlNode).IsAssignableFrom(valueType))
1406
 29
        return true;
1407
#if !NET20
1408
 314
      if (typeof(XObject).IsAssignableFrom(valueType))
1409
 20
        return true;
1410
#endif
1411

  
1412
 294
      return false;
1413
 343
    }
1414
  }
1415
}
1416
#endif