using System;
using System.Collections.Generic;
using System.Globalization;
using System.Numerics;
using System.Xml;
using System.Xml.Linq;
using DPumpHydr.WinFrmUI.WenSkin.Json.Utilities;
namespace DPumpHydr.WinFrmUI.WenSkin.Json.Converters
{
///
/// Converts XML to and from JSON.
///
public class XmlNodeConverter : JsonConverter
{
private const string TextName = "#text";
private const string CommentName = "#comment";
private const string CDataName = "#cdata-section";
private const string WhitespaceName = "#whitespace";
private const string SignificantWhitespaceName = "#significant-whitespace";
private const string DeclarationName = "?xml";
private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
///
/// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
///
/// The name of the deserialize root element.
public string DeserializeRootElementName { get; set; }
///
/// Gets or sets a flag to indicate whether to write the Json.NET array attribute.
/// This attribute helps preserve arrays when converting the written XML back to JSON.
///
/// true if the array attibute is written to the XML; otherwise, false.
public bool WriteArrayAttribute { get; set; }
///
/// Gets or sets a value indicating whether to write the root JSON object.
///
/// true if the JSON root object is omitted; otherwise, false.
public bool OmitRootObject { get; set; }
///
/// Writes the JSON representation of the object.
///
/// The to write to.
/// The calling serializer.
/// The value.
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IXmlNode node = WrapXml(value);
XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
PushParentNamespaces(node, manager);
if (!OmitRootObject)
{
writer.WriteStartObject();
}
SerializeNode(writer, node, manager, !OmitRootObject);
if (!OmitRootObject)
{
writer.WriteEndObject();
}
}
private IXmlNode WrapXml(object value)
{
if (value is XObject)
{
return XContainerWrapper.WrapNode((XObject)value);
}
if (value is XmlNode)
{
return XmlNodeWrapper.WrapNode((XmlNode)value);
}
throw new ArgumentException("Value must be an XML object.", "value");
}
private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
{
List list = null;
IXmlNode xmlNode = node;
while ((xmlNode = xmlNode.ParentNode) != null)
{
if (xmlNode.NodeType == XmlNodeType.Element)
{
if (list == null)
{
list = new List();
}
list.Add(xmlNode);
}
}
if (list == null)
{
return;
}
list.Reverse();
foreach (IXmlNode item in list)
{
manager.PushScope();
foreach (IXmlNode attribute in item.Attributes)
{
if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns")
{
manager.AddNamespace(attribute.LocalName, attribute.Value);
}
}
}
}
private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
{
string text = ((node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) ? null : manager.LookupPrefix(node.NamespaceUri));
if (!string.IsNullOrEmpty(text))
{
return text + ":" + XmlConvert.DecodeName(node.LocalName);
}
return XmlConvert.DecodeName(node.LocalName);
}
private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager)
{
switch (node.NodeType)
{
case XmlNodeType.Attribute:
if (node.NamespaceUri == "http://james.newtonking.com/projects/json")
{
return "$" + node.LocalName;
}
return "@" + ResolveFullName(node, manager);
case XmlNodeType.CDATA:
return "#cdata-section";
case XmlNodeType.Comment:
return "#comment";
case XmlNodeType.Element:
if (node.NamespaceUri == "http://james.newtonking.com/projects/json")
{
return "$" + node.LocalName;
}
return ResolveFullName(node, manager);
case XmlNodeType.ProcessingInstruction:
return "?" + ResolveFullName(node, manager);
case XmlNodeType.DocumentType:
return "!" + ResolveFullName(node, manager);
case XmlNodeType.XmlDeclaration:
return "?xml";
case XmlNodeType.SignificantWhitespace:
return "#significant-whitespace";
case XmlNodeType.Text:
return "#text";
case XmlNodeType.Whitespace:
return "#whitespace";
default:
throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
}
}
private bool IsArray(IXmlNode node)
{
if (node.Attributes != null)
{
foreach (IXmlNode attribute in node.Attributes)
{
if (attribute.LocalName == "Array" && attribute.NamespaceUri == "http://james.newtonking.com/projects/json")
{
return XmlConvert.ToBoolean(attribute.Value);
}
}
}
return false;
}
private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
{
Dictionary> dictionary = new Dictionary>();
for (int i = 0; i < node.ChildNodes.Count; i++)
{
IXmlNode xmlNode = node.ChildNodes[i];
string propertyName = GetPropertyName(xmlNode, manager);
if (!dictionary.TryGetValue(propertyName, out var value))
{
value = new List();
dictionary.Add(propertyName, value);
}
value.Add(xmlNode);
}
foreach (KeyValuePair> item in dictionary)
{
List value2 = item.Value;
if (value2.Count == 1 && !IsArray(value2[0]))
{
SerializeNode(writer, value2[0], manager, writePropertyName);
continue;
}
string key = item.Key;
if (writePropertyName)
{
writer.WritePropertyName(key);
}
writer.WriteStartArray();
for (int j = 0; j < value2.Count; j++)
{
SerializeNode(writer, value2[j], manager, writePropertyName: false);
}
writer.WriteEndArray();
}
}
private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
{
switch (node.NodeType)
{
case XmlNodeType.Document:
case XmlNodeType.DocumentFragment:
SerializeGroupedNodes(writer, node, manager, writePropertyName);
break;
case XmlNodeType.Element:
if (IsArray(node) && AllSameName(node) && node.ChildNodes.Count > 0)
{
SerializeGroupedNodes(writer, node, manager, writePropertyName: false);
break;
}
manager.PushScope();
foreach (IXmlNode attribute in node.Attributes)
{
if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/")
{
string prefix = ((attribute.LocalName != "xmlns") ? XmlConvert.DecodeName(attribute.LocalName) : string.Empty);
string value = attribute.Value;
manager.AddNamespace(prefix, value);
}
}
if (writePropertyName)
{
writer.WritePropertyName(GetPropertyName(node, manager));
}
if (!ValueAttributes(node.Attributes) && node.ChildNodes.Count == 1 && node.ChildNodes[0].NodeType == XmlNodeType.Text)
{
writer.WriteValue(node.ChildNodes[0].Value);
}
else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
{
if (((IXmlElement)node).IsEmpty)
{
writer.WriteNull();
}
else
{
writer.WriteValue(string.Empty);
}
}
else
{
writer.WriteStartObject();
for (int i = 0; i < node.Attributes.Count; i++)
{
SerializeNode(writer, node.Attributes[i], manager, writePropertyName: true);
}
SerializeGroupedNodes(writer, node, manager, writePropertyName: true);
writer.WriteEndObject();
}
manager.PopScope();
break;
case XmlNodeType.Comment:
if (writePropertyName)
{
writer.WriteComment(node.Value);
}
break;
case XmlNodeType.Attribute:
case XmlNodeType.Text:
case XmlNodeType.CDATA:
case XmlNodeType.ProcessingInstruction:
case XmlNodeType.Whitespace:
case XmlNodeType.SignificantWhitespace:
if ((!(node.NamespaceUri == "http://www.w3.org/2000/xmlns/") || !(node.Value == "http://james.newtonking.com/projects/json")) && (!(node.NamespaceUri == "http://james.newtonking.com/projects/json") || !(node.LocalName == "Array")))
{
if (writePropertyName)
{
writer.WritePropertyName(GetPropertyName(node, manager));
}
writer.WriteValue(node.Value);
}
break;
case XmlNodeType.XmlDeclaration:
{
IXmlDeclaration xmlDeclaration = (IXmlDeclaration)node;
writer.WritePropertyName(GetPropertyName(node, manager));
writer.WriteStartObject();
if (!string.IsNullOrEmpty(xmlDeclaration.Version))
{
writer.WritePropertyName("@version");
writer.WriteValue(xmlDeclaration.Version);
}
if (!string.IsNullOrEmpty(xmlDeclaration.Encoding))
{
writer.WritePropertyName("@encoding");
writer.WriteValue(xmlDeclaration.Encoding);
}
if (!string.IsNullOrEmpty(xmlDeclaration.Standalone))
{
writer.WritePropertyName("@standalone");
writer.WriteValue(xmlDeclaration.Standalone);
}
writer.WriteEndObject();
break;
}
case XmlNodeType.DocumentType:
{
IXmlDocumentType xmlDocumentType = (IXmlDocumentType)node;
writer.WritePropertyName(GetPropertyName(node, manager));
writer.WriteStartObject();
if (!string.IsNullOrEmpty(xmlDocumentType.Name))
{
writer.WritePropertyName("@name");
writer.WriteValue(xmlDocumentType.Name);
}
if (!string.IsNullOrEmpty(xmlDocumentType.Public))
{
writer.WritePropertyName("@public");
writer.WriteValue(xmlDocumentType.Public);
}
if (!string.IsNullOrEmpty(xmlDocumentType.System))
{
writer.WritePropertyName("@system");
writer.WriteValue(xmlDocumentType.System);
}
if (!string.IsNullOrEmpty(xmlDocumentType.InternalSubset))
{
writer.WritePropertyName("@internalSubset");
writer.WriteValue(xmlDocumentType.InternalSubset);
}
writer.WriteEndObject();
break;
}
default:
throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
}
}
private static bool AllSameName(IXmlNode node)
{
foreach (IXmlNode childNode in node.ChildNodes)
{
if (childNode.LocalName != node.LocalName)
{
return false;
}
}
return true;
}
///
/// Reads the JSON representation of the object.
///
/// The to read from.
/// Type of the object.
/// The existing value of object being read.
/// The calling serializer.
/// The object value.
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
IXmlDocument xmlDocument = null;
IXmlNode xmlNode = null;
if (typeof(XObject).IsAssignableFrom(objectType))
{
if (objectType != typeof(XDocument) && objectType != typeof(XElement))
{
throw new JsonSerializationException("XmlNodeConverter only supports deserializing XDocument or XElement.");
}
xmlDocument = new XDocumentWrapper(new XDocument());
xmlNode = xmlDocument;
}
if (typeof(XmlNode).IsAssignableFrom(objectType))
{
if (objectType != typeof(XmlDocument))
{
throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
}
xmlDocument = new XmlDocumentWrapper(new XmlDocument
{
XmlResolver = null
});
xmlNode = xmlDocument;
}
if (xmlDocument == null || xmlNode == null)
{
throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
}
if (reader.TokenType != JsonToken.StartObject)
{
throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
}
if (!string.IsNullOrEmpty(DeserializeRootElementName))
{
ReadElement(reader, xmlDocument, xmlNode, DeserializeRootElementName, manager);
}
else
{
reader.Read();
DeserializeNode(reader, xmlDocument, manager, xmlNode);
}
if (objectType == typeof(XElement))
{
XElement obj = (XElement)xmlDocument.DocumentElement.WrappedNode;
obj.Remove();
return obj;
}
return xmlDocument.WrappedNode;
}
private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode)
{
switch (propertyName)
{
case "#text":
currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
return;
case "#cdata-section":
currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
return;
case "#whitespace":
currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
return;
case "#significant-whitespace":
currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
return;
}
if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
{
CreateInstruction(reader, document, currentNode, propertyName);
}
else if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase))
{
CreateDocumentType(reader, document, currentNode);
}
else if (reader.TokenType == JsonToken.StartArray)
{
ReadArrayElements(reader, document, propertyName, currentNode, manager);
}
else
{
ReadElement(reader, document, currentNode, propertyName, manager);
}
}
private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
{
if (string.IsNullOrEmpty(propertyName))
{
throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML.");
}
Dictionary attributeNameValues = ReadAttributeElements(reader, manager);
string prefix = MiscellaneousUtils.GetPrefix(propertyName);
if (propertyName.StartsWith('@'))
{
string text = propertyName.Substring(1);
string prefix2 = MiscellaneousUtils.GetPrefix(text);
AddAttribute(reader, document, currentNode, text, manager, prefix2);
return;
}
if (propertyName.StartsWith('$'))
{
switch (propertyName)
{
case "$values":
propertyName = propertyName.Substring(1);
prefix = manager.LookupPrefix("http://james.newtonking.com/projects/json");
CreateElement(reader, document, currentNode, propertyName, manager, prefix, attributeNameValues);
return;
case "$id":
case "$ref":
case "$type":
case "$value":
{
string attributeName = propertyName.Substring(1);
string attributePrefix = manager.LookupPrefix("http://james.newtonking.com/projects/json");
AddAttribute(reader, document, currentNode, attributeName, manager, attributePrefix);
return;
}
}
}
CreateElement(reader, document, currentNode, propertyName, manager, prefix, attributeNameValues);
}
private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string elementPrefix, Dictionary attributeNameValues)
{
IXmlElement xmlElement = CreateElement(elementName, document, elementPrefix, manager);
currentNode.AppendChild(xmlElement);
foreach (KeyValuePair attributeNameValue in attributeNameValues)
{
string text = XmlConvert.EncodeName(attributeNameValue.Key);
string prefix = MiscellaneousUtils.GetPrefix(attributeNameValue.Key);
IXmlNode attributeNode = ((!string.IsNullOrEmpty(prefix)) ? document.CreateAttribute(text, manager.LookupNamespace(prefix) ?? string.Empty, attributeNameValue.Value) : document.CreateAttribute(text, attributeNameValue.Value));
xmlElement.SetAttributeNode(attributeNode);
}
if (reader.TokenType == JsonToken.String || reader.TokenType == JsonToken.Integer || reader.TokenType == JsonToken.Float || reader.TokenType == JsonToken.Boolean || reader.TokenType == JsonToken.Date)
{
string text2 = ConvertTokenToXmlValue(reader);
if (text2 != null)
{
xmlElement.AppendChild(document.CreateTextNode(text2));
}
}
else if (reader.TokenType != JsonToken.Null)
{
if (reader.TokenType != JsonToken.EndObject)
{
manager.PushScope();
DeserializeNode(reader, document, manager, xmlElement);
manager.PopScope();
}
manager.RemoveNamespace(string.Empty, manager.DefaultNamespace);
}
}
private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string attributeName, XmlNamespaceManager manager, string attributePrefix)
{
string text = XmlConvert.EncodeName(attributeName);
string value = reader.Value.ToString();
IXmlNode attributeNode = ((!string.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(text, manager.LookupNamespace(attributePrefix), value) : document.CreateAttribute(text, value));
((IXmlElement)currentNode).SetAttributeNode(attributeNode);
}
private string ConvertTokenToXmlValue(JsonReader reader)
{
if (reader.TokenType == JsonToken.String)
{
if (reader.Value == null)
{
return null;
}
return reader.Value.ToString();
}
if (reader.TokenType == JsonToken.Integer)
{
if (reader.Value is BigInteger)
{
return ((BigInteger)reader.Value).ToString(CultureInfo.InvariantCulture);
}
return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
}
if (reader.TokenType == JsonToken.Float)
{
if (reader.Value is decimal)
{
return XmlConvert.ToString((decimal)reader.Value);
}
if (reader.Value is float)
{
return XmlConvert.ToString((float)reader.Value);
}
return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
}
if (reader.TokenType == JsonToken.Boolean)
{
return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
}
if (reader.TokenType == JsonToken.Date)
{
if (reader.Value is DateTimeOffset)
{
return XmlConvert.ToString((DateTimeOffset)reader.Value);
}
DateTime dateTime = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture);
return XmlConvert.ToString(dateTime, DateTimeUtils.ToSerializationMode(dateTime.Kind));
}
if (reader.TokenType == JsonToken.Null)
{
return null;
}
throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
}
private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
{
string prefix = MiscellaneousUtils.GetPrefix(propertyName);
IXmlElement xmlElement = CreateElement(propertyName, document, prefix, manager);
currentNode.AppendChild(xmlElement);
int num = 0;
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
DeserializeValue(reader, document, manager, propertyName, xmlElement);
num++;
}
if (WriteArrayAttribute)
{
AddJsonArrayAttribute(xmlElement, document);
}
if (num != 1 || !WriteArrayAttribute)
{
return;
}
foreach (IXmlNode childNode in xmlElement.ChildNodes)
{
IXmlElement xmlElement2 = childNode as IXmlElement;
if (xmlElement2 != null && xmlElement2.LocalName == propertyName)
{
AddJsonArrayAttribute(xmlElement2, document);
break;
}
}
}
private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document)
{
element.SetAttributeNode(document.CreateAttribute("json:Array", "http://james.newtonking.com/projects/json", "true"));
if (element is XElementWrapper && element.GetPrefixOfNamespace("http://james.newtonking.com/projects/json") == null)
{
element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", "http://james.newtonking.com/projects/json"));
}
}
private Dictionary ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
{
Dictionary dictionary = new Dictionary();
bool flag = false;
bool flag2 = false;
if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null && reader.TokenType != JsonToken.Boolean && reader.TokenType != JsonToken.Integer && reader.TokenType != JsonToken.Float && reader.TokenType != JsonToken.Date && reader.TokenType != JsonToken.StartConstructor)
{
while (!flag && !flag2 && reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
{
string text = reader.Value.ToString();
if (!string.IsNullOrEmpty(text))
{
switch (text[0])
{
case '@':
{
text = text.Substring(1);
reader.Read();
string value = ConvertTokenToXmlValue(reader);
dictionary.Add(text, value);
if (IsNamespaceAttribute(text, out var prefix))
{
manager.AddNamespace(prefix, value);
}
break;
}
case '$':
switch (text)
{
case "$values":
case "$id":
case "$ref":
case "$type":
case "$value":
{
string text2 = manager.LookupPrefix("http://james.newtonking.com/projects/json");
if (text2 == null)
{
int? num = null;
while (manager.LookupNamespace("json" + num) != null)
{
num = num.GetValueOrDefault() + 1;
}
text2 = "json" + num;
dictionary.Add("xmlns:" + text2, "http://james.newtonking.com/projects/json");
manager.AddNamespace(text2, "http://james.newtonking.com/projects/json");
}
if (text == "$values")
{
flag = true;
break;
}
text = text.Substring(1);
reader.Read();
if (!JsonTokenUtils.IsPrimitiveToken(reader.TokenType))
{
throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType);
}
string value = ((reader.Value != null) ? reader.Value.ToString() : null);
dictionary.Add(text2 + ":" + text, value);
break;
}
default:
flag = true;
break;
}
break;
default:
flag = true;
break;
}
}
else
{
flag = true;
}
break;
}
case JsonToken.EndObject:
flag2 = true;
break;
case JsonToken.Comment:
flag2 = true;
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType);
}
}
}
return dictionary;
}
private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
{
if (propertyName == "?xml")
{
string version = null;
string encoding = null;
string standalone = null;
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
switch (reader.Value.ToString())
{
case "@version":
reader.Read();
version = reader.Value.ToString();
break;
case "@encoding":
reader.Read();
encoding = reader.Value.ToString();
break;
case "@standalone":
reader.Read();
standalone = reader.Value.ToString();
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
}
}
IXmlNode newChild = document.CreateXmlDeclaration(version, encoding, standalone);
currentNode.AppendChild(newChild);
}
else
{
IXmlNode newChild2 = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
currentNode.AppendChild(newChild2);
}
}
private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode)
{
string name = null;
string publicId = null;
string systemId = null;
string internalSubset = null;
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
switch (reader.Value.ToString())
{
case "@name":
reader.Read();
name = reader.Value.ToString();
break;
case "@public":
reader.Read();
publicId = reader.Value.ToString();
break;
case "@system":
reader.Read();
systemId = reader.Value.ToString();
break;
case "@internalSubset":
reader.Read();
internalSubset = reader.Value.ToString();
break;
default:
throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
}
}
IXmlNode newChild = document.CreateXmlDocumentType(name, publicId, systemId, internalSubset);
currentNode.AppendChild(newChild);
}
private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
{
string text = XmlConvert.EncodeName(elementName);
string text2 = (string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix));
if (string.IsNullOrEmpty(text2))
{
return document.CreateElement(text);
}
return document.CreateElement(text, text2);
}
private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
{
do
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
{
if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
{
throw JsonSerializationException.Create(reader, "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.");
}
string text = reader.Value.ToString();
reader.Read();
if (reader.TokenType == JsonToken.StartArray)
{
int num = 0;
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
DeserializeValue(reader, document, manager, text, currentNode);
num++;
}
if (num != 1 || !WriteArrayAttribute)
{
break;
}
foreach (IXmlNode childNode in currentNode.ChildNodes)
{
IXmlElement xmlElement = childNode as IXmlElement;
if (xmlElement != null && xmlElement.LocalName == text)
{
AddJsonArrayAttribute(xmlElement, document);
break;
}
}
}
else
{
DeserializeValue(reader, document, manager, text, currentNode);
}
break;
}
case JsonToken.StartConstructor:
{
string propertyName = reader.Value.ToString();
while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
{
DeserializeValue(reader, document, manager, propertyName, currentNode);
}
break;
}
case JsonToken.Comment:
currentNode.AppendChild(document.CreateComment((string)reader.Value));
break;
case JsonToken.EndObject:
case JsonToken.EndArray:
return;
default:
throw JsonSerializationException.Create(reader, "Unexpected JsonToken when deserializing node: " + reader.TokenType);
}
}
while (reader.TokenType == JsonToken.PropertyName || reader.Read());
}
///
/// Checks if the attributeName is a namespace attribute.
///
/// Attribute name to test.
/// The attribute name prefix if it has one, otherwise an empty string.
/// true if attribute name is for a namespace attribute, otherwise false.
private bool IsNamespaceAttribute(string attributeName, out string prefix)
{
if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
{
if (attributeName.Length == 5)
{
prefix = string.Empty;
return true;
}
if (attributeName[5] == ':')
{
prefix = attributeName.Substring(6, attributeName.Length - 6);
return true;
}
}
prefix = null;
return false;
}
private bool ValueAttributes(List c)
{
foreach (IXmlNode item in c)
{
if (item.NamespaceUri != "http://james.newtonking.com/projects/json")
{
return true;
}
}
return false;
}
///
/// Determines whether this instance can convert the specified value type.
///
/// Type of the value.
///
/// true if this instance can convert the specified value type; otherwise, false.
///
public override bool CanConvert(Type valueType)
{
if (typeof(XObject).IsAssignableFrom(valueType))
{
return true;
}
if (typeof(XmlNode).IsAssignableFrom(valueType))
{
return true;
}
return false;
}
}
}