| /// <summary> |
| /// Class used to parse csdl to create the metatdata object |
| /// </summary> |
| /// |
| |
| namespace DataJS.Tests |
| { |
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| using System.Linq; |
| using System.Xml.Linq; |
| |
| |
| public static class CsdlReader |
| { |
| static readonly string knownNamespace = "http://docs.oasis-open.org"; |
| static readonly string[] repeatingElements = |
| { |
| "Action", |
| "ActionImport", |
| "Annotation", |
| "Annotations", |
| "Apply", |
| "Binary", |
| "Bool", |
| "Cast", |
| "Collection", |
| "ComplexType", |
| "Date", |
| "DateTimeOffset", |
| "Decimal", |
| "Duration", |
| "EntitySet", |
| "EntityType", |
| "EnumMember", |
| "EnumType", |
| "Float", |
| "Function", |
| "FunctionImport", |
| "Guid", |
| "If", |
| "Int", |
| "IsOf", |
| "Key", |
| "LabeledElement", |
| "LabeledElementReference", |
| "Member", |
| "NavigationProperty", |
| "NavigationPropertyBinding", |
| "NavigationPropertyPath", |
| "Null", |
| "OnDelete", |
| "Path", |
| "Parameter", |
| "Property", |
| "PropertyPath", |
| "PropertyRef", |
| "PropertyValue", |
| "Record", |
| "ReferentialConstraint", |
| "String", |
| "Schema", |
| "Singleton", |
| "Term", |
| "TimeOfDay", |
| "TypeDefinition", |
| "UrlRef", |
| "Reference", |
| "Include", |
| "IncludeAnnotations" |
| }; |
| |
| public static Dictionary<string, object> ReadCsdl(TextReader payload) |
| { |
| return BuildElementJsonObject(XElement.Load(payload)); |
| } |
| |
| /// <summary> |
| /// Build the attribute object |
| /// </summary> |
| /// <param name="xmlAttributes">IEnumberable of XAttributes to build the attribute object</param> |
| /// <returns>The JsonObject containing the name-value pairs for an element's attributes</returns> |
| static Dictionary<string, object> BuildAttributeJsonObject(IEnumerable<XAttribute> xmlAttributes) |
| { |
| Dictionary<string, object> jsonObject = new Dictionary<string, object>(); |
| |
| foreach (XAttribute attribute in xmlAttributes) |
| { |
| if (!attribute.IsNamespaceDeclaration) |
| { |
| string attributeNamespace = attribute.Name.Namespace.ToString(); |
| if (string.IsNullOrEmpty(attributeNamespace) || |
| attributeNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase)) |
| { |
| jsonObject[MakeFirstLetterLowercase(attribute.Name.LocalName)] = attribute.Value; |
| } |
| } |
| } |
| |
| return jsonObject; |
| } |
| |
| /// <summary> |
| /// Creates a JsonObject from an XML container element with each attribute or subelement as a property |
| /// </summary> |
| /// <param name="container">The XML container</param> |
| /// <param name="buildValue">Function that builds a value from a property element</param> |
| /// <returns>The JsonObject containing the name-value pairs</returns> |
| public static Dictionary<string, object> BuildElementJsonObject(XElement container) |
| { |
| if (container == null) |
| { |
| return null; |
| } |
| |
| Dictionary<string, object> jsonObject = new Dictionary<string, object>(); |
| string keyName = MakeFirstLetterLowercase(container.Name.LocalName); |
| |
| if (container.HasAttributes || container.HasElements) |
| { |
| Dictionary<string, List<Dictionary<string, object>>> repeatingObjectArrays = new Dictionary<string, List<Dictionary<string, object>>>(); |
| |
| jsonObject = BuildAttributeJsonObject(container.Attributes()); |
| |
| foreach (XElement propertyElement in container.Elements()) |
| { |
| string propertyName = MakeFirstLetterLowercase(propertyElement.Name.LocalName); |
| string properyNamespace = propertyElement.Name.Namespace.ToString(); |
| |
| if (string.IsNullOrEmpty(properyNamespace) || properyNamespace.StartsWith(knownNamespace, StringComparison.InvariantCultureIgnoreCase)) |
| { |
| // Check to see if the element is repeating and needs to be an array |
| if (repeatingElements.Contains(propertyElement.Name.LocalName)) |
| { |
| // See if property was already created as an array, if not then create it |
| if (!repeatingObjectArrays.ContainsKey(propertyName)) |
| { |
| repeatingObjectArrays.Add(propertyName, new List<Dictionary<string, object>>()); |
| } |
| |
| repeatingObjectArrays[propertyName].Add(BuildElementJsonObject(propertyElement)); |
| } |
| else |
| { |
| jsonObject[propertyName] = BuildElementJsonObject(propertyElement); |
| } |
| } |
| } |
| |
| foreach (string key in repeatingObjectArrays.Keys) |
| { |
| jsonObject[key] = repeatingObjectArrays[key].ToArray(); |
| } |
| } |
| else |
| { |
| jsonObject[MakeFirstLetterLowercase(container.Name.LocalName)] = container.Value; |
| } |
| |
| return jsonObject; |
| } |
| |
| /// <summary> |
| /// Makes the first letter of a string lowercase |
| /// </summary> |
| /// <param name="name">The string to be modified</param> |
| /// <returns>Modified string</returns> |
| private static string MakeFirstLetterLowercase(string str) |
| { |
| if (!string.IsNullOrWhiteSpace(str)) |
| { |
| if (str.Length > 1 && !(str[1].ToString() == str[1].ToString().ToUpper())) |
| { |
| return str[0].ToString().ToLower() + str.Substring(1); |
| } |
| else |
| { |
| return str; |
| } |
| } |
| |
| return str; |
| } |
| } |
| } |