private void DeserializeValue(JsonReader reader, XmlDocument document, XmlNamespaceManager manager, string propertyName, XmlNode currentNode)
{
switch (propertyName)
{
case TextName:
currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
break;
case CDataName:
currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
break;
case WhitespaceName:
currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
break;
case SignificantWhitespaceName:
currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
break;
default:
// processing instructions and the xml declaration start with ?
if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
{
if (propertyName == DeclarationName)
{
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 new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
}
}
XmlDeclaration declaration = document.CreateXmlDeclaration(version, encoding, standalone);
currentNode.AppendChild(declaration);
}
else
{
XmlProcessingInstruction instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
currentNode.AppendChild(instruction);
}
}
else
{
// deserialize xml element
bool finishedAttributes = false;
bool finishedElement = false;
string elementPrefix = GetPrefix(propertyName);
Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
if (reader.TokenType == JsonToken.StartArray)
{
XmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
currentNode.AppendChild(nestedArrayElement);
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
}
return;
}
// a string token means the element only has a single text child
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)
{
// read properties until first non-attribute is encountered
while (!finishedAttributes && !finishedElement && reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
string attributeName = reader.Value.ToString();
if (attributeName[0] == '@')
{
attributeName = attributeName.Substring(1);
reader.Read();
string attributeValue = reader.Value.ToString();
attributeNameValues.Add(attributeName, attributeValue);
string namespacePrefix;
if (IsNamespaceAttribute(attributeName, out namespacePrefix))
{
manager.AddNamespace(namespacePrefix, attributeValue);
}
}
else
{
finishedAttributes = true;
}
break;
case JsonToken.EndObject:
finishedElement = true;
break;
default:
throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
}
}
}
// have to wait until attributes have been parsed before creating element
// attributes may contain namespace info used by the element
XmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
currentNode.AppendChild(element);
// add attributes to newly created element
foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
{
string attributePrefix = GetPrefix(nameValue.Key);
XmlAttribute attribute = (!string.IsNullOrEmpty(attributePrefix))
? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix))
: document.CreateAttribute(nameValue.Key);
attribute.Value = nameValue.Value;
element.SetAttributeNode(attribute);
}
if (reader.TokenType == JsonToken.String)
{
element.AppendChild(document.CreateTextNode(reader.Value.ToString()));
}
else if (reader.TokenType == JsonToken.Integer)
{
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((long)reader.Value)));
}
else if (reader.TokenType == JsonToken.Float)
{
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((double)reader.Value)));
}
else if (reader.TokenType == JsonToken.Boolean)
{
element.AppendChild(document.CreateTextNode(XmlConvert.ToString((bool)reader.Value)));
}
else if (reader.TokenType == JsonToken.Date)
{
DateTime d = (DateTime)reader.Value;
element.AppendChild(document.CreateTextNode(XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind))));
}
else if (reader.TokenType == JsonToken.Null)
{
// empty element. do nothing
}
else
{
// finished element will have no children to deserialize
if (!finishedElement)
{
manager.PushScope();
DeserializeNode(reader, document, manager, element);
manager.PopScope();
}
}
}
break;
}
}