You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by bi...@apache.org on 2014/05/09 09:22:29 UTC

[20/24] a) Convert all the DataJS supported functionality from V3 to V4. 1. Remove all the Json verbose logic, make the DataJS accepted and returned javascript object be in Json light format. (Since Json verbose has been completely removed on V4, making

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/e387fc92/JSLib/src/odata-atom.js
----------------------------------------------------------------------
diff --git a/JSLib/src/odata-atom.js b/JSLib/src/odata-atom.js
index d92c2a6..40983d8 100644
--- a/JSLib/src/odata-atom.js
+++ b/JSLib/src/odata-atom.js
@@ -1,1411 +1,1411 @@
-/// <reference path="odata-utils.js" />
-/// <reference path="odata-handler.js" />
-/// <reference path="odata-xml.js" />
-
-// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
-// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
-// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-// odata-atom.js
-
-(function (window, undefined) {
-
-    var datajs = window.datajs || {};
-    var odata = window.OData || {};
-
-    // imports
-    var contains = datajs.contains;
-    var djsassert = datajs.djsassert;
-    var isArray = datajs.isArray;
-    var isObject = datajs.isObject;
-    var isXmlNSDeclaration = datajs.isXmlNSDeclaration;
-    var normalizeURI = datajs.normalizeURI;
-    var parseInt10 = datajs.parseInt10;
-    var xmlAppendChild = datajs.xmlAppendChild;
-    var xmlAppendChildren = datajs.xmlAppendChildren
-    var xmlAttributes = datajs.xmlAttributes;
-    var xmlAttributeNode = datajs.xmlAttributeNode;
-    var xmlAttributeValue = datajs.xmlAttributeValue;
-    var xmlBaseURI = datajs.xmlBaseURI;
-    var xmlChildElements = datajs.xmlChildElements;
-    var xmlDom = datajs.xmlDom;
-    var xmlFirstChildElement = datajs.xmlFirstChildElement;
-    var xmlFindElementByPath = datajs.xmlFindElementByPath;
-    var xmlFindNodeByPath = datajs.xmlFindNodeByPath;
-    var xmlInnerText = datajs.xmlInnerText;
-    var xmlLocalName = datajs.xmlLocalName;
-    var xmlNamespaceURI = datajs.xmlNamespaceURI;
-    var xmlNewAttribute = datajs.xmlNewAttribute;
-    var xmlNewElement = datajs.xmlNewElement;
-    var xmlNewFragment = datajs.xmlNewFragment;
-    var xmlNewNodeByPath = datajs.xmlNewNodeByPath;
-    var xmlNewNSDeclaration = datajs.xmlNewNSDeclaration;
-    var xmlNewText = datajs.xmlNewText;
-    var xmlNodeValue = datajs.xmlNodeValue;
-    var xmlNS = datajs.xmlNS;
-    var xmlnsNS = datajs.xmlnsNS;
-    var xmlQualifiedName = datajs.xmlQualifiedName;
-    var xmlParse = datajs.xmlParse;
-    var xmlSerialize = datajs.xmlSerialize;
-    var xmlSerializeDescendants = datajs.xmlSerializeDescendants;
-    var xmlSibling = datajs.xmlSibling;
-    var w3org = datajs.w3org;
-
-    var adoDs = odata.adoDs;
-    var contentType = odata.contentType;
-    var createAttributeExtension = odata.createAttributeExtension;
-    var createElementExtension = odata.createElementExtension;
-    var handler = odata.handler;
-    var isPrimitiveEdmType = odata.isPrimitiveEdmType;
-    var isFeed = odata.isFeed;
-    var isNamedStream = odata.isNamedStream;
-    var lookupEntityType = odata.lookupEntityType;
-    var lookupComplexType = odata.lookupComplexType;
-    var lookupProperty = odata.lookupProperty;
-    var navigationPropertyKind = odata.navigationPropertyKind;
-    var MAX_DATA_SERVICE_VERSION = odata.MAX_DATA_SERVICE_VERSION;
-    var maxVersion = odata.maxVersion;
-    var odataXmlNs = odata.odataXmlNs;
-    var odataMetaXmlNs = odata.odataMetaXmlNs;
-    var odataMetaPrefix = odata.odataMetaPrefix;
-    var odataPrefix = odata.odataPrefix;
-    var odataRelatedPrefix = odata.odataRelatedPrefix;
-    var odataScheme = odata.odataScheme;
-    var parseBool = odata.parseBool;
-    var parseDateTime = odata.parseDateTime;
-    var parseDateTimeOffset = odata.parseDateTimeOffset;
-    var parseDuration = odata.parseDuration;
-    var parseTimezone = odata.parseTimezone;
-    var xmlNewODataElement = odata.xmlNewODataElement;
-    var xmlNewODataElementInfo = odata.xmlNewODataElementInfo;
-    var xmlNewODataMetaAttribute = odata.xmlNewODataMetaAttribute;
-    var xmlNewODataMetaElement = odata.xmlNewODataMetaElement;
-    var xmlNewODataDataElement = odata.xmlNewODataDataElement;
-    var xmlReadODataEdmPropertyValue = odata.xmlReadODataEdmPropertyValue;
-    var xmlReadODataProperty = odata.xmlReadODataProperty;
-
-    // CONTENT START
-
-    var atomPrefix = "a";
-
-    var atomXmlNs = w3org + "2005/Atom";                    // http://www.w3.org/2005/Atom
-    var appXmlNs = w3org + "2007/app";                      // http://www.w3.org/2007/app
-
-    var odataEditMediaPrefix = adoDs + "/edit-media/";        // http://schemas.microsoft.com/ado/2007/08/dataservices/edit-media
-    var odataMediaResourcePrefix = adoDs + "/mediaresource/"; // http://schemas.microsoft.com/ado/2007/08/dataservices/mediaresource
-    var odataRelatedLinksPrefix = adoDs + "/relatedlinks/";   // http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks
-
-    var atomAcceptTypes = ["application/atom+xml", "application/atomsvc+xml", "application/xml"];
-    var atomMediaType = atomAcceptTypes[0];
-
-    // These are the namespaces that are not considered ATOM extension namespaces.
-    var nonExtensionNamepaces = [atomXmlNs, appXmlNs, xmlNS, xmlnsNS];
-
-    // These are entity property mapping paths that have well-known paths.
-    var knownCustomizationPaths = {
-        SyndicationAuthorEmail: "author/email",
-        SyndicationAuthorName: "author/name",
-        SyndicationAuthorUri: "author/uri",
-        SyndicationContributorEmail: "contributor/email",
-        SyndicationContributorName: "contributor/name",
-        SyndicationContributorUri: "contributor/uri",
-        SyndicationPublished: "published",
-        SyndicationRights: "rights",
-        SyndicationSummary: "summary",
-        SyndicationTitle: "title",
-        SyndicationUpdated: "updated"
-    };
-
-    var expandedFeedCustomizationPath = function (path) {
-        /// <summary>Returns an expanded customization path if it's well-known.</summary>
-        /// <param name="path" type="String">Path to expand.</param>
-        /// <returns type="String">Expanded path or just 'path' otherwise.</returns>
-
-        return knownCustomizationPaths[path] || path;
-    };
-
-    var isExtensionNs = function (nsURI) {
-        /// <summary>Checks whether the specified namespace is an extension namespace to ATOM.</summary>
-        /// <param type="String" name="nsURI">Namespace to check.</param>
-        /// <returns type="Boolean">true if nsURI is an extension namespace to ATOM; false otherwise.</returns>
-
-        return !(contains(nonExtensionNamepaces, nsURI));
-    };
-
-    var atomFeedCustomization = function (customizationModel, entityType, model, propertyName, suffix) {
-        /// <summary>Creates an object describing a feed customization that was delcared in an OData conceptual schema.</summary>
-        /// <param name="customizationModel" type="Object">Object describing the customization delcared in the conceptual schema.</param>
-        /// <param name="entityType" type="Object">Object describing the entity type that owns the customization in an OData conceputal schema.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="propertyName" type="String" optional="true">Name of the property to which this customization applies.</param>
-        /// <param name="suffix" type="String" optional="true">Suffix to feed customization properties in the conceptual schema.</param>
-        /// <returns type="Object">Object that describes an applicable feed customization.</returns>
-
-        suffix = suffix || "";
-        var targetPath = customizationModel["FC_TargetPath" + suffix];
-        if (!targetPath) {
-            return null;
-        }
-
-        var sourcePath = customizationModel["FC_SourcePath" + suffix];
-        var targetXmlPath = expandedFeedCustomizationPath(targetPath);
-
-        var propertyPath = propertyName ? propertyName + (sourcePath ? "/" + sourcePath : "") : sourcePath;
-        var propertyType = propertyPath && lookupPropertyType(model, entityType, propertyPath);
-        var nsURI = customizationModel["FC_NsUri" + suffix] || null;
-        var nsPrefix = customizationModel["FC_NsPrefix" + suffix] || null;
-        var keepinContent = customizationModel["FC_KeepInContent" + suffix] || "";
-
-        if (targetPath !== targetXmlPath) {
-            nsURI = atomXmlNs;
-            nsPrefix = atomPrefix;
-        }
-
-        return {
-            contentKind: customizationModel["FC_ContentKind" + suffix],
-            keepInContent: keepinContent.toLowerCase() === "true",
-            nsPrefix: nsPrefix,
-            nsURI: nsURI,
-            propertyPath: propertyPath,
-            propertyType: propertyType,
-            entryPath: targetXmlPath
-        };
-    };
-
-    var atomApplyAllFeedCustomizations = function (entityType, model, callback) {
-        /// <summary>Gets all the feed customizations that have to be applied to an entry as per the enity type declared in an OData conceptual schema.</summary>
-        /// <param name="entityType" type="Object">Object describing an entity type in a conceptual schema.</param>
-        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-        /// <param name="callback" type="Function">Callback function to be invoked for each feed customization that needs to be applied.</param>
-
-        var customizations = [];
-        while (entityType) {
-            var sourcePath = entityType.FC_SourcePath;
-            var customization = atomFeedCustomization(entityType, entityType, model);
-            if (customization) {
-                callback(customization);
-            }
-
-            var properties = entityType.property || [];
-            var i, len;
-            for (i = 0, len = properties.length; i < len; i++) {
-                var property = properties[i];
-                var suffixCounter = 0;
-                var suffix = "";
-
-                while (customization = atomFeedCustomization(property, entityType, model, property.name, suffix)) {
-                    callback(customization);
-                    suffixCounter++;
-                    suffix = "_" + suffixCounter;
-                }
-            }
-            entityType = lookupEntityType(entityType.baseType, model);
-        }
-        return customizations;
-    };
-
-    var atomReadExtensionAttributes = function (domElement) {
-        /// <summary>Reads ATOM extension attributes (any attribute not in the Atom namespace) from a DOM element.</summary>
-        /// <param name="domElement">DOM element with zero or more extension attributes.</param>
-        /// <returns type="Array">An array of extension attribute representations.</returns>
-
-        var extensions = [];
-        xmlAttributes(domElement, function (attribute) {
-            var nsURI = xmlNamespaceURI(attribute);
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-        return extensions;
-    };
-
-    var atomReadExtensionElement = function (domElement) {
-        /// <summary>Reads an ATOM extension element (an element not in the ATOM namespaces).</summary>
-        /// <param name="domElement">DOM element not part of the atom namespace.</param>
-        /// <returns type="Object">Object representing the extension element.</returns>
-
-        return createElementExtension(domElement, /*addNamespaceURI*/true);
-    };
-
-    var atomReadDocument = function (domElement, baseURI, model) {
-        /// <summary>Reads an ATOM entry, feed or service document, producing an object model in return.</summary>
-        /// <param name="domElement">Top-level ATOM DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM document.</param>
-        /// <param name="model" type="Object">Object that describes the conceptual schema.</param>
-        /// <returns type="Object">The object model representing the specified element, undefined if the top-level element is not part of the ATOM specification.</returns>
-
-        var nsURI = xmlNamespaceURI(domElement);
-        var localName = xmlLocalName(domElement);
-
-        // Handle service documents.
-        if (nsURI === appXmlNs && localName === "service") {
-            return atomReadServiceDocument(domElement, baseURI);
-        }
-
-        // Handle feed and entry elements.
-        if (nsURI === atomXmlNs) {
-            if (localName === "feed") {
-                return atomReadFeed(domElement, baseURI, model);
-            }
-            if (localName === "entry") {
-                return atomReadEntry(domElement, baseURI, model);
-            }
-        }
-
-        // Allow undefined to be returned.
-    };
-
-    var atomReadAdvertisedActionOrFunction = function (domElement, baseURI) {
-        /// <summary>Reads the DOM element for an action or a function in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or function target url.</param>
-        /// <returns type="Object">Object with title, target, and metadata fields.</returns>
-
-        var extensions = [];
-        var result = { extensions: extensions };
-        xmlAttributes(domElement, function (attribute) {
-            var localName = xmlLocalName(attribute);
-            var nsURI = xmlNamespaceURI(attribute);
-            var value = xmlNodeValue(attribute);
-
-            if (nsURI === null) {
-                if (localName === "title" || localName === "metadata") {
-                    result[localName] = value;
-                    return;
-                }
-                if (localName === "target") {
-                    result.target = normalizeURI(value, xmlBaseURI(domElement, baseURI));
-                    return;
-                }
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-        return result;
-    };
-
-    var atomReadAdvertisedAction = function (domElement, baseURI, parentMetadata) {
-        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
-        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
-
-        var actions = parentMetadata.actions = parentMetadata.actions || [];
-        actions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
-    };
-
-    var atomReadAdvertisedFunction = function (domElement, baseURI, parentMetadata) {
-        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
-        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
-
-        var functions = parentMetadata.functions = parentMetadata.functions || [];
-        functions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
-    };
-
-    var atomReadFeed = function (domElement, baseURI, model) {
-        /// <summary>Reads a DOM element for an ATOM feed, producing an object model in return.</summary>
-        /// <param name="domElement">ATOM feed DOM element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM feed.</param>
-        /// <param name="model">Metadata that describes the conceptual schema.</param>
-        /// <returns type="Object">A new object representing the feed.</returns>
-
-        var extensions = atomReadExtensionAttributes(domElement);
-        var feedMetadata = { feed_extensions: extensions };
-        var results = [];
-
-        var feed = { __metadata: feedMetadata, results: results };
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === odataMetaXmlNs) {
-                if (localName === "count") {
-                    feed.__count = parseInt(xmlInnerText(child), 10);
-                    return;
-                }
-                if (localName === "action") {
-                    atomReadAdvertisedAction(child, baseURI, feedMetadata);
-                    return;
-                }
-                if (localName === "function") {
-                    atomReadAdvertisedFunction(child, baseURI, feedMetadata);
-                    return;
-                }
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createElementExtension(child));
-                return;
-            }
-
-            // The element should belong to the ATOM namespace.
-            djsassert(nsURI === atomXmlNs, "atomReadFeed - child feed element is not in the atom namespace!!");
-
-            if (localName === "entry") {
-                results.push(atomReadEntry(child, baseURI, model));
-                return;
-            }
-            if (localName === "link") {
-                atomReadFeedLink(child, feed, baseURI);
-                return;
-            }
-            if (localName === "id") {
-                feedMetadata.uri = normalizeURI(xmlInnerText(child), baseURI);
-                feedMetadata.uri_extensions = atomReadExtensionAttributes(child);
-                return;
-            }
-            if (localName === "title") {
-                feedMetadata.title = xmlInnerText(child) || "";
-                feedMetadata.title_extensions = atomReadExtensionAttributes(child);
-                return;
-            }
-        });
-
-        return feed;
-    };
-
-    var atomReadFeedLink = function (domElement, feed, baseURI) {
-        /// <summary>Reads an ATOM link DOM element for a feed.</summary>
-        /// <param name="domElement">ATOM link DOM element.</param>
-        /// <param name="feed">Feed object to be annotated with the link data.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
-
-        var link = atomReadLink(domElement, baseURI);
-        var href = link.href;
-        var rel = link.rel;
-        var extensions = link.extensions;
-        var metadata = feed.__metadata;
-
-        if (rel === "next") {
-            feed.__next = href;
-            metadata.next_extensions = extensions;
-            return;
-        }
-        if (rel === "self") {
-            metadata.self = href;
-            metadata.self_extensions = extensions;
-            return;
-        }
-    };
-
-    var atomReadLink = function (domElement, baseURI) {
-        /// <summary>Reads an ATOM link DOM element.</summary>
-        /// <param name="linkElement">DOM element to read.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the link href.</param>
-        /// <returns type="Object">A link element representation.</returns>
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        var extensions = [];
-        var link = { extensions: extensions, baseURI: baseURI };
-
-        xmlAttributes(domElement, function (attribute) {
-            var nsURI = xmlNamespaceURI(attribute);
-            var localName = xmlLocalName(attribute);
-            var value = attribute.value;
-
-            if (localName === "href") {
-                link.href = normalizeURI(value, baseURI);
-                return;
-            }
-            if (localName === "type" || localName === "rel") {
-                link[localName] = value;
-                return;
-            }
-
-            if (isExtensionNs(nsURI)) {
-                extensions.push(createAttributeExtension(attribute, true));
-            }
-        });
-
-        if (!link.href) {
-            throw { error: "href attribute missing on link element", element: domElement };
-        }
-
-        return link;
-    };
-
-    var atomGetObjectValueByPath = function (path, item) {
-        /// <summary>Gets a slashed path value from the specified item.</summary>
-        /// <param name="path" type="String">Property path to read ('/'-separated).</param>
-        /// <param name="item" type="Object">Object to get value from.</param>
-        /// <returns>The property value, possibly undefined if any path segment is missing.</returns>
-
-        // Fast path.
-        if (path.indexOf('/') === -1) {
-            return item[path];
-        } else {
-            var parts = path.split('/');
-            var i, len;
-            for (i = 0, len = parts.length; i < len; i++) {
-                // Avoid traversing a null object.
-                if (item === null) {
-                    return undefined;
-                }
-
-                item = item[parts[i]];
-                if (item === undefined) {
-                    return item;
-                }
-            }
-
-            return item;
-        }
-    };
-
-    var atomSetEntryValueByPath = function (path, target, value, propertyType) {
-        /// <summary>Sets a slashed path value on the specified target.</summary>
-        /// <param name="path" type="String">Property path to set ('/'-separated).</param>
-        /// <param name="target" type="Object">Object to set value on.</param>
-        /// <param name="value">Value to set.</param>
-        /// <param name="propertyType" type="String" optional="true">Property type to set in metadata.</param>
-
-        var propertyName;
-        if (path.indexOf('/') === -1) {
-            target[path] = value;
-            propertyName = path;
-        } else {
-            var parts = path.split('/');
-            var i, len;
-            for (i = 0, len = (parts.length - 1); i < len; i++) {
-                // We construct each step of the way if the property is missing;
-                // if it's already initialized to null, we stop further processing.
-                var next = target[parts[i]];
-                if (next === undefined) {
-                    next = {};
-                    target[parts[i]] = next;
-                } else if (next === null) {
-                    return;
-                }
-                target = next;
-            }
-            propertyName = parts[i];
-            target[propertyName] = value;
-        }
-
-        if (propertyType) {
-            var metadata = target.__metadata = target.__metadata || {};
-            var properties = metadata.properties = metadata.properties || {};
-            var property = properties[propertyName] = properties[propertyName] || {};
-            property.type = propertyType;
-        }
-    };
-
-    var atomApplyCustomizationToEntryObject = function (customization, domElement, entry) {
-        /// <summary>Applies a specific feed customization item to an object.</summary>
-        /// <param name="customization">Object with customization description.</param>
-        /// <param name="sourcePath">Property path to set ('source' in the description).</param>
-        /// <param name="entryElement">XML element for the entry that corresponds to the object being read.</param>
-        /// <param name="entryObject">Object being read.</param>
-        /// <param name="propertyType" type="String">Name of property type to set.</param>
-        /// <param name="suffix" type="String">Suffix to feed customization properties.</param>
-
-        var propertyPath = customization.propertyPath;
-        // If keepInConent equals true or the property value is null we do nothing as this overrides any other customization.
-        if (customization.keepInContent || atomGetObjectValueByPath(propertyPath, entry) === null) {
-            return;
-        }
-
-        var xmlNode = xmlFindNodeByPath(domElement, customization.nsURI, customization.entryPath);
-
-        // If the XML tree does not contain the necessary elements to read the value,
-        // then it shouldn't be considered null, but rather ignored at all. This prevents
-        // the customization from generating the object path down to the property.
-        if (!xmlNode) {
-            return;
-        }
-
-        var propertyType = customization.propertyType;
-        var propertyValue;
-
-        if (customization.contentKind === "xhtml") {
-            // Treat per XHTML in http://tools.ietf.org/html/rfc4287#section-3.1.1, including the DIV
-            // in the content.
-            propertyValue = xmlSerializeDescendants(xmlNode);
-        } else {
-            propertyValue = xmlReadODataEdmPropertyValue(xmlNode, propertyType || "Edm.String");
-        }
-        // Set the value on the entry.
-        atomSetEntryValueByPath(propertyPath, entry, propertyValue, propertyType);
-    };
-
-    var lookupPropertyType = function (metadata, owningType, path) {
-        /// <summary>Looks up the type of a property given its path in an entity type.</summary>
-        /// <param name="metadata">Metadata in which to search for base and complex types.</param>
-        /// <param name="owningType">Type to which property belongs.</param>
-        /// <param name="path" type="String" mayBeNull="false">Property path to look at.</param>
-        /// <returns type="String">The name of the property type; possibly null.</returns>
-
-        var parts = path.split("/");
-        var i, len;
-        while (owningType) {
-            // Keep track of the type being traversed, necessary for complex types.
-            var traversedType = owningType;
-
-            for (i = 0, len = parts.length; i < len; i++) {
-                // Traverse down the structure as necessary.
-                var properties = traversedType.property;
-                if (!properties) {
-                    break;
-                }
-
-                // Find the property by scanning the property list (might be worth pre-processing).
-                var propertyFound = lookupProperty(properties, parts[i]);
-                if (!propertyFound) {
-                    break;
-                }
-
-                var propertyType = propertyFound.type;
-
-                // We could in theory still be missing types, but that would
-                // be caused by a malformed path.
-                if (!propertyType || isPrimitiveEdmType(propertyType)) {
-                    return propertyType || null;
-                }
-
-                traversedType = lookupComplexType(propertyType, metadata);
-                if (!traversedType) {
-                    return null;
-                }
-            }
-
-            // Traverse up the inheritance chain.
-            owningType = lookupEntityType(owningType.baseType, metadata);
-        }
-
-        return null;
-    };
-
-    var atomReadEntry = function (domElement, baseURI, model) {
-        /// <summary>Reads a DOM element for an ATOM entry, producing an object model in return.</summary>
-        /// <param name="domElement">ATOM entry DOM element.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM entry.</param>
-        /// <param name="model">Metadata that describes the conceptual schema.</param>
-        /// <returns type="Object">A new object representing the entry.</returns>
-
-        var entryMetadata = {};
-        var entry = { __metadata: entryMetadata };
-
-        var etag = xmlAttributeValue(domElement, "etag", odataMetaXmlNs);
-        if (etag) {
-            entryMetadata.etag = etag;
-        }
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "id") {
-                    atomReadEntryId(child, entryMetadata, baseURI);
-                    return;
-                }
-                if (localName === "category") {
-                    atomReadEntryType(child, entryMetadata);
-                    return;
-                }
-                if (localName === "content") {
-                    atomReadEntryContent(child, entry, entryMetadata, baseURI);
-                    return;
-                }
-                if (localName === "link") {
-                    atomReadEntryLink(child, entry, entryMetadata, baseURI, model);
-                    return;
-                }
-                return;
-            }
-
-            if (nsURI === odataMetaXmlNs) {
-                if (localName === "properties") {
-                    atomReadEntryStructuralObject(child, entry, entryMetadata);
-                    return;
-                }
-                if (localName === "action") {
-                    atomReadAdvertisedAction(child, baseURI, entryMetadata);
-                    return;
-                }
-                if (localName === "function") {
-                    atomReadAdvertisedFunction(child, baseURI, entryMetadata);
-                    return;
-                }
-            }
-        });
-
-        // Apply feed customizations if applicable
-        var entityType = lookupEntityType(entryMetadata.type, model);
-        atomApplyAllFeedCustomizations(entityType, model, function (customization) {
-            atomApplyCustomizationToEntryObject(customization, domElement, entry);
-        });
-
-        return entry;
-    };
-
-    var atomReadEntryId = function (domElement, entryMetadata, baseURI) {
-        /// <summary>Reads an ATOM entry id DOM element.</summary>
-        /// <param name="domElement">ATOM id DOM element.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the id information.</param>
-
-        entryMetadata.uri = normalizeURI(xmlInnerText(domElement), xmlBaseURI(domElement, baseURI));
-        entryMetadata.uri_extensions = atomReadExtensionAttributes(domElement);
-    };
-
-    var atomReadEntryType = function (domElement, entryMetadata) {
-        /// <summary>Reads type information from an ATOM category DOM element.</summary>
-        /// <param name="domElement">ATOM category DOM element.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the type information.</param>
-
-        if (xmlAttributeValue(domElement, "scheme") === odataScheme) {
-            if (entryMetadata.type) {
-                throw { message: "Invalid AtomPub document: multiple category elements defining the entry type were encounterd withing an entry", element: domElement };
-            }
-
-            var typeExtensions = [];
-            xmlAttributes(domElement, function (attribute) {
-                var nsURI = xmlNamespaceURI(attribute);
-                var localName = xmlLocalName(attribute);
-
-                if (!nsURI) {
-                    if (localName !== "scheme" && localName !== "term") {
-                        typeExtensions.push(createAttributeExtension(attribute, true));
-                    }
-                    return;
-                }
-
-                if (isExtensionNs(nsURI)) {
-                    typeExtensions.push(createAttributeExtension(attribute, true));
-                }
-            });
-
-            entryMetadata.type = xmlAttributeValue(domElement, "term");
-            entryMetadata.type_extensions = typeExtensions;
-        }
-    };
-
-    var atomReadEntryContent = function (domElement, entry, entryMetadata, baseURI) {
-        /// <summary>Reads an ATOM content DOM element.</summary>
-        /// <param name="domElement">ATOM content DOM element.</param>
-        /// <param name="entry">Entry object to update with information.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the content information.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the Atom entry content.</param>
-
-        var src = xmlAttributeValue(domElement, "src");
-        var type = xmlAttributeValue(domElement, "type");
-
-        if (src) {
-            if (!type) {
-                throw {
-                    message: "Invalid AtomPub document: content element must specify the type attribute if the src attribute is also specified",
-                    element: domElement
-                };
-            }
-
-            entryMetadata.media_src = normalizeURI(src, xmlBaseURI(domElement, baseURI));
-            entryMetadata.content_type = type;
-        }
-
-        xmlChildElements(domElement, function (child) {
-            if (src) {
-                throw { message: "Invalid AtomPub document: content element must not have child elements if the src attribute is specified", element: domElement };
-            }
-
-            if (xmlNamespaceURI(child) === odataMetaXmlNs && xmlLocalName(child) === "properties") {
-                atomReadEntryStructuralObject(child, entry, entryMetadata);
-            }
-        });
-    };
-
-    var atomReadEntryLink = function (domElement, entry, entryMetadata, baseURI, model) {
-        /// <summary>Reads a link element on an entry.</summary>
-        /// <param name="atomEntryLink">'link' element on the entry.</param>
-        /// <param name="entry" type="Object">Entry object to update with the link data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the link metadata.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing the link href.</param>
-        /// <param name="model" type="Object">Metadata that describes the conceptual schema.</param>
-
-        var link = atomReadLink(domElement, baseURI);
-
-        var rel = link.rel;
-        var href = link.href;
-        var extensions = link.extensions;
-
-        if (rel === "self") {
-            entryMetadata.self = href;
-            entryMetadata.self_link_extensions = extensions;
-            return;
-        }
-
-        if (rel === "edit") {
-            entryMetadata.edit = href;
-            entryMetadata.edit_link_extensions = extensions;
-            return;
-        }
-
-        if (rel === "edit-media") {
-            entryMetadata.edit_media = link.href;
-            entryMetadata.edit_media_extensions = extensions;
-            atomReadLinkMediaEtag(link, entryMetadata);
-            return;
-        }
-
-        // This might be a named stream edit link
-        if (rel.indexOf(odataEditMediaPrefix) === 0) {
-            atomReadNamedStreamEditLink(link, entry, entryMetadata);
-            return;
-        }
-
-        // This might be a named stram media resource (read) link
-        if (rel.indexOf(odataMediaResourcePrefix) === 0) {
-            atomReadNamedStreamSelfLink(link, entry, entryMetadata);
-            return;
-        }
-
-        // This might be a navigation property
-        if (rel.indexOf(odataRelatedPrefix) === 0) {
-            atomReadNavPropLink(domElement, link, entry, entryMetadata, model);
-            return;
-        }
-
-        if (rel.indexOf(odataRelatedLinksPrefix) === 0) {
-            atomReadNavPropRelatedLink(link, entryMetadata);
-            return;
-        }
-    };
-
-    var atomReadNavPropRelatedLink = function (link, entryMetadata) {
-        /// <summary>Reads a link represnting the links related to a navigation property in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entryMetadata" type="Object">Entry metadata object to update with the related links information.</param>
-
-        var propertyName = link.rel.substring(odataRelatedLinksPrefix.length);
-        djsassert(propertyName, "atomReadNavPropRelatedLink - property name is null, empty or undefined!");
-
-        // Set the extra property information on the entry object metadata.
-        entryMetadata.properties = entryMetadata.properties || {};
-        var propertyMetadata = entryMetadata.properties[propertyName] = entryMetadata.properties[propertyName] || {};
-
-        propertyMetadata.associationuri = link.href;
-        propertyMetadata.associationuri_extensions = link.extensions;
-    };
-
-    var atomReadNavPropLink = function (domElement, link, entry, entryMetadata, model) {
-        /// <summary>Reads a link representing a navigation property in an OData Atom document.</summary>
-        /// <param name="domElement">DOM element for a navigation property in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the navigation property.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the navigation property metadata.</param>
-        /// <param name="model" type="Object">Metadata that describes the conceptual schema.</param>
-
-        // Get any inline data.
-        var inlineData;
-        var inlineElement = xmlFirstChildElement(domElement, odataMetaXmlNs, "inline");
-        if (inlineElement) {
-            var inlineDocRoot = xmlFirstChildElement(inlineElement);
-            var inlineBaseURI = xmlBaseURI(inlineElement, link.baseURI);
-            inlineData = inlineDocRoot ? atomReadDocument(inlineDocRoot, inlineBaseURI, model) : null;
-        } else {
-            // If the link has no inline content, we consider it deferred.
-            inlineData = { __deferred: { uri: link.href} };
-        }
-
-        var propertyName = link.rel.substring(odataRelatedPrefix.length);
-
-        // Set the property value on the entry object.
-        entry[propertyName] = inlineData;
-
-        // Set the extra property information on the entry object metadata.
-        entryMetadata.properties = entryMetadata.properties || {};
-        var propertyMetadata = entryMetadata.properties[propertyName] = entryMetadata.properties[propertyName] || {};
-
-        propertyMetadata.extensions = link.extensions;
-    };
-
-    var atomReadNamedStreamEditLink = function (link, entry, entryMetadata) {
-        /// <summary>Reads a link representing the edit-media url of a named stream in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the named stream data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the named stream metadata.</param>
-
-        var propertyName = link.rel.substring(odataEditMediaPrefix.length);
-        djsassert(propertyName, "atomReadNamedStreamEditLink - property name is null, empty or undefined!");
-
-        var namedStreamMediaResource = atomGetEntryNamedStreamMediaResource(propertyName, entry, entryMetadata);
-        var mediaResource = namedStreamMediaResource.value;
-        var mediaResourceMetadata = namedStreamMediaResource.metadata;
-
-        var editMedia = link.href;
-
-        mediaResource.edit_media = editMedia;
-        mediaResource.content_type = link.type;
-        mediaResourceMetadata.edit_media_extensions = link.extensions;
-
-        // If there is only the edit link, make it the media self link as well.
-        mediaResource.media_src = mediaResource.media_src || editMedia;
-        mediaResourceMetadata.media_src_extensions = mediaResourceMetadata.media_src_extensions || [];
-
-        atomReadLinkMediaEtag(link, mediaResource);
-    };
-
-    var atomReadNamedStreamSelfLink = function (link, entry, entryMetadata) {
-        /// <summary>Reads a link representing the self url of a named stream in an OData Atom document.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object to update with the named stream data.</param>
-        /// <param name="entryMetadata">Entry metadata object to update with the named stream metadata.</param>
-
-        var propertyName = link.rel.substring(odataMediaResourcePrefix.length);
-        djsassert(propertyName, "atomReadNamedStreamEditLink - property name is null, empty or undefined!");
-
-        var namedStreamMediaResource = atomGetEntryNamedStreamMediaResource(propertyName, entry, entryMetadata);
-        var mediaResource = namedStreamMediaResource.value;
-        var mediaResourceMetadata = namedStreamMediaResource.metadata;
-
-        mediaResource.media_src = link.href;
-        mediaResourceMetadata.media_src_extensions = link.extensions;
-        mediaResource.content_type = link.type;
-    };
-
-    var atomGetEntryNamedStreamMediaResource = function (name, entry, entryMetadata) {
-        /// <summary>Gets the media resource object and metadata object for a named stream in an entry object.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="entry" type="Object">Entry object from which the media resource object will be obtained.</param>
-        /// <param name="entryMetadata" type="Object">Entry metadata object from which the media resource metadata object will be obtained.</param>
-        /// <remarks>
-        ///    If the entry doest' have a media resource for the named stream indicated by the name argument, then this function will create a new
-        ///    one along with its metadata object.
-        /// <remarks>
-        /// <returns type="Object"> Object containing the value and metadata of the named stream's media resource. <returns>
-
-        entryMetadata.properties = entryMetadata.properties || {};
-
-        var mediaResourceMetadata = entryMetadata.properties[name];
-        var mediaResource = entry[name] && entry[name].__mediaresource;
-
-        if (!mediaResource) {
-            mediaResource = {};
-            entry[name] = { __mediaresource: mediaResource };
-            entryMetadata.properties[name] = mediaResourceMetadata = {};
-        }
-        return { value: mediaResource, metadata: mediaResourceMetadata };
-    };
-
-    var atomReadLinkMediaEtag = function (link, mediaResource) {
-        /// <summary>Gets the media etag from the link extensions and updates the media resource object with it.</summary>
-        /// <param name="link" type="Object">Object representing the parsed link DOM element.</param>
-        /// <param name="mediaResource" type="Object">Object containing media information for an OData Atom entry.</param>
-        /// <remarks>
-        ///    The function will remove the extension object for the etag if it finds it in the link extensions and will set
-        ///    its value under the media_etag property of the mediaResource object.
-        /// <remarks>
-        /// <returns type="Object"> Object containing the value and metadata of the named stream's media resource. <returns>
-
-        var extensions = link.extensions;
-        var i, len;
-        for (i = 0, len = extensions.length; i < len; i++) {
-            if (extensions[i].namespaceURI === odataMetaXmlNs && extensions[i].name === "etag") {
-                mediaResource.media_etag = extensions[i].value;
-                extensions.splice(i, 1);
-                return;
-            }
-        }
-    };
-
-    var atomReadEntryStructuralObject = function (domElement, parent, parentMetadata) {
-        /// <summary>Reads an atom entry's property as a structural object and sets its value in the parent and the metadata in the parentMetadata objects.</summary>
-        /// <param name="propertiesElement">XML element for the 'properties' node.</param>
-        /// <param name="parent">
-        ///     Object that will contain the property value. It can be either an antom entry or
-        ///     an atom complex property object.
-        /// </param>
-        /// <param name="parentMetadata">Object that will contain the property metadata. It can be either an atom entry metadata or a complex property metadata object</param>
-
-        xmlChildElements(domElement, function (child) {
-            var property = xmlReadODataProperty(child);
-            if (property) {
-                var propertyName = property.name;
-                var propertiesMetadata = parentMetadata.properties = parentMetadata.properties || {};
-                propertiesMetadata[propertyName] = property.metadata;
-                parent[propertyName] = property.value;
-            }
-        });
-    };
-
-    var atomReadServiceDocument = function (domElement, baseURI) {
-        /// <summary>Reads an AtomPub service document</summary>
-        /// <param name="atomServiceDoc">DOM element for the root of an AtomPub service document</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document.</param>
-        /// <returns type="Object">An object that contains the properties of the service document</returns>
-
-        var workspaces = [];
-        var extensions = [];
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-        // Find all the workspace elements.
-        xmlChildElements(domElement, function (child) {
-            if (xmlNamespaceURI(child) === appXmlNs && xmlLocalName(child) === "workspace") {
-                workspaces.push(atomReadServiceDocumentWorkspace(child, baseURI));
-                return;
-            }
-            extensions.push(createElementExtension(child));
-        });
-
-        // AtomPub (RFC 5023 Section 8.3.1) says a service document MUST contain one or
-        // more workspaces. Throw if we don't find any.
-        if (workspaces.length === 0) {
-            throw { message: "Invalid AtomPub service document: No workspace element found.", element: domElement };
-        }
-
-        return { workspaces: workspaces, extensions: extensions };
-    };
-
-    var atomReadServiceDocumentWorkspace = function (domElement, baseURI) {
-        /// <summary>Reads a single workspace element from an AtomPub service document</summary>
-        /// <param name="domElement">DOM element that represents a workspace of an AtomPub service document</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document workspace.</param>
-        /// <returns type="Object">An object that contains the properties of the workspace</returns>
-
-        var collections = [];
-        var extensions = [];
-        var title; // = undefined;
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "title") {
-                    if (title !== undefined) {
-                        throw { message: "Invalid AtomPub service document: workspace has more than one child title element", element: child };
-                    }
-
-                    title = xmlInnerText(child);
-                    return;
-                }
-            }
-
-            if (nsURI === appXmlNs) {
-                if (localName === "collection") {
-                    collections.push(atomReadServiceDocumentCollection(child, baseURI));
-                }
-                return;
-            }
-            extensions.push(atomReadExtensionElement(child));
-        });
-
-        return { title: title || "", collections: collections, extensions: extensions };
-    };
-
-    var atomReadServiceDocumentCollection = function (domElement, baseURI) {
-        /// <summary>Reads a service document collection element into an object.</summary>
-        /// <param name="domElement">DOM element that represents a collection of an AtomPub service document.</param>
-        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the AtomPub service document collection.</param>
-        /// <returns type="Object">An object that contains the properties of the collection.</returns>
-
-
-        var href = xmlAttributeValue(domElement, "href");
-
-        if (!href) {
-            throw { message: "Invalid AtomPub service document: collection has no href attribute", element: domElement };
-        }
-
-        baseURI = xmlBaseURI(domElement, baseURI);
-        href = normalizeURI(href, xmlBaseURI(domElement, baseURI));
-        var extensions = [];
-        var title; // = undefined;
-
-        xmlChildElements(domElement, function (child) {
-            var nsURI = xmlNamespaceURI(child);
-            var localName = xmlLocalName(child);
-
-            if (nsURI === atomXmlNs) {
-                if (localName === "title") {
-                    if (title !== undefined) {
-                        throw { message: "Invalid AtomPub service document: collection has more than one child title element", element: child };
-                    }
-                    title = xmlInnerText(child);
-                }
-                return;
-            }
-
-            if (nsURI !== appXmlNs) {
-                extensions.push(atomReadExtensionElement(domElement));
-            }
-        });
-
-        // AtomPub (RFC 5023 Section 8.3.3) says the collection element MUST contain
-        // a title element. It's likely to be problematic if the service doc doesn't
-        // have one so here we throw.
-        if (!title) {
-            throw { message: "Invalid AtomPub service document: collection has no title element", element: domElement };
-        }
-
-        return { title: title, href: href, extensions: extensions };
-    };
-
-    var atomNewElement = function (dom, name, children) {
-        /// <summary>Creates a new DOM element in the Atom namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the Atom element to create.</param>
-        /// <param name="children" type="Array">Array containing DOM nodes or string values that will be added as children of the new DOM element.</param>
-        /// <returns>New DOM element in the Atom namespace.</returns>
-        /// <remarks>
-        ///    If a value in the children collection is a string, then a new DOM text node is going to be created
-        ///    for it and then appended as a child of the new DOM Element.
-        /// </remarks>
-
-        return xmlNewElement(dom, atomXmlNs, xmlQualifiedName(atomPrefix, name), children);
-    };
-
-    var atomNewAttribute = function (dom, name, value) {
-        /// <summary>Creates a new DOM attribute for an Atom element in the default namespace.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Local name of the OData attribute to create.</param>
-        /// <param name="value">Attribute value.</param>
-        /// <returns>New DOM attribute in the default namespace.</returns>
-
-        return xmlNewAttribute(dom, null, name, value);
-    };
-
-    var atomCanRemoveProperty = function (propertyElement) {
-        /// <summary>Checks whether the property represented by domElement can be removed from the atom document DOM tree.</summary>
-        /// <param name="propertyElement">DOM element for the property to test.</param>
-        /// <remarks>
-        ///     The property can only be removed if it doens't have any children and only has namespace or type declaration attributes.
-        /// </remarks>
-        /// <returns type="Boolean">True is the property can be removed; false otherwise.</returns>
-
-        if (propertyElement.childNodes.length > 0) {
-            return false;
-        }
-
-        var isEmpty = true;
-        var attributes = propertyElement.attributes;
-        var i, len;
-        for (i = 0, len = attributes.length; i < len && isEmpty; i++) {
-            var attribute = attributes[i];
-
-            isEmpty = isEmpty && isXmlNSDeclaration(attribute) ||
-                 (xmlNamespaceURI(attribute) == odataMetaXmlNs && xmlLocalName(attribute) === "type");
-        }
-        return isEmpty;
-    };
-
-    var atomNewODataNavigationProperty = function (dom, name, kind, value, model) {
-        /// <summary>Creates a new Atom link DOM element for a navigation property in an OData Atom document.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Property name.</param>
-        /// <param name="kind" type="String">Navigation property kind. Expected values are "deferred", "entry", or "feed".</param>
-        /// <param name="value" optional="true" mayBeNull="true">Value of the navigation property, if any.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new Atom link DOM element for the navigation property and the
-        ///     required data service version for this property.
-        /// </returns>
-
-        var linkType = null;
-        var linkContent = null;
-        var linkContentBodyData = null;
-        var href = "";
-
-        if (kind !== "deferred") {
-            linkType = atomNewAttribute(dom, "type", "application/atom+xml;type=" + kind);
-            linkContent = xmlNewODataMetaElement(dom, "inline");
-
-            if (value) {
-                href = value.__metadata && value.__metadata.uri || "";
-                linkContentBodyData =
-                    atomNewODataFeed(dom, value, model) ||
-                    atomNewODataEntry(dom, value, model);
-                xmlAppendChild(linkContent, linkContentBodyData.element);
-            }
-        } else {
-            href = value.__deferred.uri;
-        }
-
-        var navProp = atomNewElement(dom, "link", [
-            atomNewAttribute(dom, "href", href),
-            atomNewAttribute(dom, "rel", normalizeURI(name, odataRelatedPrefix)),
-            linkType,
-            linkContent
-        ]);
-
-        return xmlNewODataElementInfo(navProp, linkContentBodyData ? linkContentBodyData.dsv : "1.0");
-    };
-
-    var atomNewODataEntryDataItem = function (dom, name, value, dataItemMetadata, dataItemModel, model) {
-        /// <summary>Creates a new DOM element for a data item in an entry, complex property, or collection property.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="name" type="String">Data item name.</param>
-        /// <param name="value" optional="true" mayBeNull="true">Value of the data item, if any.</param>
-        /// <param name="dataItemMetadata" type="Object" optional="true">Object containing metadata about the data item.</param>
-        /// <param name="dataItemModel" type="Object" optional="true">Object describing the data item in an OData conceptual schema.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element in the appropriate namespace for the data item and the
-        ///     required data service version for it.
-        /// </returns>
-
-        if (isNamedStream(value)) {
-            return null;
-        }
-
-        var dataElement = xmlNewODataDataElement(dom, name, value, dataItemMetadata, dataItemModel, model);
-        if (!dataElement) {
-            // This may be a navigation property.
-            var navPropKind = navigationPropertyKind(value, dataItemModel);
-            djsassert(navPropKind !== null, "atomNewODataEntryDataItem - navigation property kind is null for property " + name);
-
-            dataElement = atomNewODataNavigationProperty(dom, name, navPropKind, value, model);
-        }
-        return dataElement;
-    };
-
-    var atomEntryCustomization = function (dom, entry, entryProperties, customization) {
-        /// <summary>Applies a feed customization by transforming an Atom entry DOM element as needed.</summary>
-        /// <param name="dom">DOM document used for creating any new DOM nodes required by the customization.</param>
-        /// <param name="entry">DOM element for the Atom entry to which the customization is going to be applied.</param>
-        /// <param name="entryProperties">DOM element containing the properties of the Atom entry.</param>
-        /// <param name="customization" type="Object">Object describing an applicable feed customization.</param>
-        /// <remarks>
-        ///     Look into the atomfeedCustomization function for a description of the customization object.
-        /// </remarks>
-        /// <returns type="String">Data service version required by the applied customization</returns>
-
-        var atomProperty = xmlFindElementByPath(entryProperties, odataXmlNs, customization.propertyPath);
-        var atomPropertyNullAttribute = atomProperty && xmlAttributeNode(atomProperty, "null", odataMetaXmlNs);
-        var atomPropertyValue;
-        var dataServiceVersion = "1.0";
-
-        if (atomPropertyNullAttribute && atomPropertyNullAttribute.value === "true") {
-            return dataServiceVersion;
-        }
-
-        if (atomProperty) {
-            atomPropertyValue = xmlInnerText(atomProperty) || "";
-            if (!customization.keepInContent) {
-                dataServiceVersion = "2.0";
-                var parent = atomProperty.parentNode;
-                var candidate = parent;
-
-                parent.removeChild(atomProperty);
-                while (candidate !== entryProperties && atomCanRemoveProperty(candidate)) {
-                    parent = candidate.parentNode;
-                    parent.removeChild(candidate);
-                    candidate = parent;
-                }
-            }
-        }
-
-        var targetNode = xmlNewNodeByPath(dom, entry,
-            customization.nsURI, customization.nsPrefix, customization.entryPath);
-
-        if (targetNode.nodeType === 2) {
-            targetNode.value = atomPropertyValue;
-            return dataServiceVersion;
-        }
-
-        var contentKind = customization.contentKind;
-        xmlAppendChildren(targetNode, [
-                contentKind && xmlNewAttribute(dom, null, "type", contentKind),
-                contentKind === "xhtml" ? xmlNewFragment(dom, atomPropertyValue) : atomPropertyValue
-        ]);
-
-        return dataServiceVersion;
-    };
-
-    var atomNewODataEntry = function (dom, data, model) {
-        /// <summary>Creates a new DOM element for an Atom entry.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="data" type="Object">Entry object in the library's internal representation.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element for the Atom entry and the required data service version for it.
-        /// </returns>
-
-        var payloadMetadata = data.__metadata || {};
-        var propertiesMetadata = payloadMetadata.properties || {};
-
-        var etag = payloadMetadata.etag;
-        var uri = payloadMetadata.uri;
-        var typeName = payloadMetadata.type;
-        var entityType = lookupEntityType(typeName, model);
-
-        var properties = xmlNewODataMetaElement(dom, "properties");
-        var entry = atomNewElement(dom, "entry", [
-            atomNewElement(dom, "author",
-                atomNewElement(dom, "name")
-            ),
-            etag && xmlNewODataMetaAttribute(dom, "etag", etag),
-            uri && atomNewElement(dom, "id", uri),
-            typeName && atomNewElement(dom, "category", [
-                atomNewAttribute(dom, "term", typeName),
-                atomNewAttribute(dom, "scheme", odataScheme)
-            ]),
-        // TODO: MLE support goes here.
-            atomNewElement(dom, "content", [
-                atomNewAttribute(dom, "type", "application/xml"),
-                properties
-            ])
-        ]);
-
-        var dataServiceVersion = "1.0";
-        for (var name in data) {
-            if (name !== "__metadata") {
-                var entryDataItemMetadata = propertiesMetadata[name] || {};
-                var entryDataItemModel = entityType && (
-                    lookupProperty(entityType.property, name) ||
-                    lookupProperty(entityType.navigationProperty, name));
-
-                var entryDataItem = atomNewODataEntryDataItem(dom, name, data[name], entryDataItemMetadata, entryDataItemModel, model);
-                if (entryDataItem) {
-                    var entryElement = entryDataItem.element;
-                    var entryElementParent = (xmlNamespaceURI(entryElement) === atomXmlNs) ? entry : properties;
-
-                    xmlAppendChild(entryElementParent, entryElement);
-                    dataServiceVersion = maxVersion(dataServiceVersion, entryDataItem.dsv);
-                }
-            }
-        }
-
-        atomApplyAllFeedCustomizations(entityType, model, function (customization) {
-            var customizationDsv = atomEntryCustomization(dom, entry, properties, customization);
-            dataServiceVersion = maxVersion(dataServiceVersion, customizationDsv);
-        });
-
-        return xmlNewODataElementInfo(entry, dataServiceVersion);
-    };
-
-    var atomNewODataFeed = function (dom, data, model) {
-        /// <summary>Creates a new DOM element for an Atom feed.</summary>
-        /// <param name="dom">DOM document used for creating the new DOM Element.</param>
-        /// <param name="data" type="Object">Feed object in the library's internal representation.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM element for the Atom feed and the required data service version for it.
-        /// </returns>
-
-        var entries = isArray(data) ? data : data.results;
-
-        if (!entries) {
-            return null;
-        }
-
-        var dataServiceVersion = "1.0";
-        var atomFeed = atomNewElement(dom, "feed");
-
-        var i, len;
-        for (i = 0, len = entries.length; i < len; i++) {
-            var atomEntryData = atomNewODataEntry(dom, entries[i], model);
-            xmlAppendChild(atomFeed, atomEntryData.element);
-            dataServiceVersion = maxVersion(dataServiceVersion, atomEntryData.dsv);
-        }
-        return xmlNewODataElementInfo(atomFeed, dataServiceVersion);
-    };
-
-    var atomNewODataDocument = function (data, model) {
-        /// <summary>Creates a new OData Atom document.</summary>
-        /// <param name="data" type="Object">Feed or entry object in the libary's internal representaion.</param>
-        /// <param name="model" type="Object" optional="true">Object describing an OData conceptual schema.</param>
-        /// <returns type="Object">
-        ///     Object containing the new DOM document for the Atom document and the required data service version for it.
-        /// </returns>
-
-        if (data) {
-            var atomRootWriter = isFeed(data) && atomNewODataFeed ||
-                isObject(data) && atomNewODataEntry;
-
-            if (atomRootWriter) {
-                var dom = xmlDom();
-                var atomRootData = atomRootWriter(dom, data, model);
-
-                if (atomRootData) {
-                    var atomRootElement = atomRootData.element;
-                    xmlAppendChildren(atomRootElement, [
-                        xmlNewNSDeclaration(dom, odataMetaXmlNs, odataMetaPrefix),
-                        xmlNewNSDeclaration(dom, odataXmlNs, odataPrefix)
-                    ]);
-                    return xmlNewODataElementInfo(xmlAppendChild(dom, atomRootElement), atomRootData.dsv);
-                }
-            }
-        }
-        return null;
-    };
-
-    var atomParser = function (handler, text, context) {
-        /// <summary>Parses an ATOM document (feed, entry or service document).</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="text" type="String">Document text.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An object representation of the document; undefined if not applicable.</returns>
-
-        if (text) {
-            var atomDoc = xmlParse(text);
-            var atomRoot = xmlFirstChildElement(atomDoc);
-            if (atomRoot) {
-                return atomReadDocument(atomRoot, null, context.metadata);
-            }
-        }
-    };
-
-    var atomSerializer = function (handler, data, context) {
-        /// <summary>Serializes an ATOM object into a document (feed or entry).</summary>
-        /// <param name="handler">This handler.</param>
-        /// <param name="data" type="Object">Representation of feed or entry.</param>
-        /// <param name="context" type="Object">Object with parsing context.</param>
-        /// <returns>An text representation of the data object; undefined if not applicable.</returns>
-
-        var cType = context.contentType = context.contentType || contentType(atomMediaType);
-        if (cType && cType.mediaType === atomMediaType) {
-            var atomDoc = atomNewODataDocument(data, context.metadata);
-            if (atomDoc) {
-                context.dataServiceVersion = maxVersion(context.dataServiceVersion || "1.0", atomDoc.dsv);
-                return xmlSerialize(atomDoc.element);
-            }
-        }
-        // Allow undefined to be returned.
-    };
-
-    odata.atomHandler = handler(atomParser, atomSerializer, atomAcceptTypes.join(","), MAX_DATA_SERVICE_VERSION);
-
-    // DATAJS INTERNAL START
-    odata.atomParser = atomParser;
-    odata.atomSerializer = atomSerializer;
-    odata.atomReadDocument = atomReadDocument;
-    odata.atomReadFeed = atomReadFeed;
-    odata.atomReadFeedLink = atomReadFeedLink;
-    odata.atomReadLink = atomReadLink;
-    odata.atomReadExtensionElement = atomReadExtensionElement;
-    odata.atomReadExtensionAttributes = atomReadExtensionAttributes;
-    odata.atomReadEntry = atomReadEntry;
-    odata.atomReadEntryType = atomReadEntryType;
-    odata.atomReadEntryContent = atomReadEntryContent;
-    odata.atomReadEntryLink = atomReadEntryLink;
-    odata.atomReadEntryStructuralObject = atomReadEntryStructuralObject;
-    odata.atomReadServiceDocument = atomReadServiceDocument;
-    odata.atomReadServiceDocumentWorkspace = atomReadServiceDocumentWorkspace;
-    odata.atomReadServiceDocumentCollection = atomReadServiceDocumentCollection;
-    odata.expandedFeedCustomizationPath = expandedFeedCustomizationPath;
-    odata.lookupPropertyType = lookupPropertyType;
-    odata.atomSetEntryValueByPath = atomSetEntryValueByPath;
-    // DATAJS INTERNAL END
-
-    // CONTENT END
+/// <reference path="odata-utils.js" />
+/// <reference path="odata-handler.js" />
+/// <reference path="odata-xml.js" />
+
+// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
+// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// odata-atom.js
+
+(function (window, undefined) {
+
+    var datajs = window.datajs || {};
+    var odata = window.OData || {};
+
+    // imports
+    var contains = datajs.contains;
+    var djsassert = datajs.djsassert;
+    var isArray = datajs.isArray;
+    var isObject = datajs.isObject;
+    var isXmlNSDeclaration = datajs.isXmlNSDeclaration;
+    var normalizeURI = datajs.normalizeURI;
+    var parseInt10 = datajs.parseInt10;
+    var xmlAppendChild = datajs.xmlAppendChild;
+    var xmlAppendChildren = datajs.xmlAppendChildren
+    var xmlAttributes = datajs.xmlAttributes;
+    var xmlAttributeNode = datajs.xmlAttributeNode;
+    var xmlAttributeValue = datajs.xmlAttributeValue;
+    var xmlBaseURI = datajs.xmlBaseURI;
+    var xmlChildElements = datajs.xmlChildElements;
+    var xmlDom = datajs.xmlDom;
+    var xmlFirstChildElement = datajs.xmlFirstChildElement;
+    var xmlFindElementByPath = datajs.xmlFindElementByPath;
+    var xmlFindNodeByPath = datajs.xmlFindNodeByPath;
+    var xmlInnerText = datajs.xmlInnerText;
+    var xmlLocalName = datajs.xmlLocalName;
+    var xmlNamespaceURI = datajs.xmlNamespaceURI;
+    var xmlNewAttribute = datajs.xmlNewAttribute;
+    var xmlNewElement = datajs.xmlNewElement;
+    var xmlNewFragment = datajs.xmlNewFragment;
+    var xmlNewNodeByPath = datajs.xmlNewNodeByPath;
+    var xmlNewNSDeclaration = datajs.xmlNewNSDeclaration;
+    var xmlNewText = datajs.xmlNewText;
+    var xmlNodeValue = datajs.xmlNodeValue;
+    var xmlNS = datajs.xmlNS;
+    var xmlnsNS = datajs.xmlnsNS;
+    var xmlQualifiedName = datajs.xmlQualifiedName;
+    var xmlParse = datajs.xmlParse;
+    var xmlSerialize = datajs.xmlSerialize;
+    var xmlSerializeDescendants = datajs.xmlSerializeDescendants;
+    var xmlSibling = datajs.xmlSibling;
+    var w3org = datajs.w3org;
+
+    var adoDs = odata.adoDs;
+    var contentType = odata.contentType;
+    var createAttributeExtension = odata.createAttributeExtension;
+    var createElementExtension = odata.createElementExtension;
+    var handler = odata.handler;
+    var isPrimitiveEdmType = odata.isPrimitiveEdmType;
+    var isFeed = odata.isFeed;
+    var isNamedStream = odata.isNamedStream;
+    var lookupEntityType = odata.lookupEntityType;
+    var lookupComplexType = odata.lookupComplexType;
+    var lookupProperty = odata.lookupProperty;
+    var navigationPropertyKind = odata.navigationPropertyKind;
+    var MAX_DATA_SERVICE_VERSION = odata.MAX_DATA_SERVICE_VERSION;
+    var maxVersion = odata.maxVersion;
+    var odataXmlNs = odata.odataXmlNs;
+    var odataMetaXmlNs = odata.odataMetaXmlNs;
+    var odataMetaPrefix = odata.odataMetaPrefix;
+    var odataPrefix = odata.odataPrefix;
+    var odataRelatedPrefix = odata.odataRelatedPrefix;
+    var odataScheme = odata.odataScheme;
+    var parseBool = odata.parseBool;
+    var parseDateTime = odata.parseDateTime;
+    var parseDateTimeOffset = odata.parseDateTimeOffset;
+    var parseDuration = odata.parseDuration;
+    var parseTimezone = odata.parseTimezone;
+    var xmlNewODataElement = odata.xmlNewODataElement;
+    var xmlNewODataElementInfo = odata.xmlNewODataElementInfo;
+    var xmlNewODataMetaAttribute = odata.xmlNewODataMetaAttribute;
+    var xmlNewODataMetaElement = odata.xmlNewODataMetaElement;
+    var xmlNewODataDataElement = odata.xmlNewODataDataElement;
+    var xmlReadODataEdmPropertyValue = odata.xmlReadODataEdmPropertyValue;
+    var xmlReadODataProperty = odata.xmlReadODataProperty;
+
+    // CONTENT START
+
+    var atomPrefix = "a";
+
+    var atomXmlNs = w3org + "2005/Atom";                    // http://www.w3.org/2005/Atom
+    var appXmlNs = w3org + "2007/app";                      // http://www.w3.org/2007/app
+
+    var odataEditMediaPrefix = adoDs + "/edit-media/";        // http://docs.oasis-open.org/odata/ns/edit-media
+    var odataMediaResourcePrefix = adoDs + "/mediaresource/"; // http://docs.oasis-open.org/odata/ns/mediaresource
+    var odataRelatedLinksPrefix = adoDs + "/relatedlinks/";   // http://docs.oasis-open.org/odata/ns/relatedlinks
+
+    var atomAcceptTypes = ["application/atom+xml", "application/atomsvc+xml", "application/xml"];
+    var atomMediaType = atomAcceptTypes[0];
+
+    // These are the namespaces that are not considered ATOM extension namespaces.
+    var nonExtensionNamepaces = [atomXmlNs, appXmlNs, xmlNS, xmlnsNS];
+
+    // These are entity property mapping paths that have well-known paths.
+    var knownCustomizationPaths = {
+        SyndicationAuthorEmail: "author/email",
+        SyndicationAuthorName: "author/name",
+        SyndicationAuthorUri: "author/uri",
+        SyndicationContributorEmail: "contributor/email",
+        SyndicationContributorName: "contributor/name",
+        SyndicationContributorUri: "contributor/uri",
+        SyndicationPublished: "published",
+        SyndicationRights: "rights",
+        SyndicationSummary: "summary",
+        SyndicationTitle: "title",
+        SyndicationUpdated: "updated"
+    };
+
+    var expandedFeedCustomizationPath = function (path) {
+        /// <summary>Returns an expanded customization path if it's well-known.</summary>
+        /// <param name="path" type="String">Path to expand.</param>
+        /// <returns type="String">Expanded path or just 'path' otherwise.</returns>
+
+        return knownCustomizationPaths[path] || path;
+    };
+
+    var isExtensionNs = function (nsURI) {
+        /// <summary>Checks whether the specified namespace is an extension namespace to ATOM.</summary>
+        /// <param type="String" name="nsURI">Namespace to check.</param>
+        /// <returns type="Boolean">true if nsURI is an extension namespace to ATOM; false otherwise.</returns>
+
+        return !(contains(nonExtensionNamepaces, nsURI));
+    };
+
+    var atomFeedCustomization = function (customizationModel, entityType, model, propertyName, suffix) {
+        /// <summary>Creates an object describing a feed customization that was delcared in an OData conceptual schema.</summary>
+        /// <param name="customizationModel" type="Object">Object describing the customization delcared in the conceptual schema.</param>
+        /// <param name="entityType" type="Object">Object describing the entity type that owns the customization in an OData conceputal schema.</param>
+        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
+        /// <param name="propertyName" type="String" optional="true">Name of the property to which this customization applies.</param>
+        /// <param name="suffix" type="String" optional="true">Suffix to feed customization properties in the conceptual schema.</param>
+        /// <returns type="Object">Object that describes an applicable feed customization.</returns>
+
+        suffix = suffix || "";
+        var targetPath = customizationModel["FC_TargetPath" + suffix];
+        if (!targetPath) {
+            return null;
+        }
+
+        var sourcePath = customizationModel["FC_SourcePath" + suffix];
+        var targetXmlPath = expandedFeedCustomizationPath(targetPath);
+
+        var propertyPath = propertyName ? propertyName + (sourcePath ? "/" + sourcePath : "") : sourcePath;
+        var propertyType = propertyPath && lookupPropertyType(model, entityType, propertyPath);
+        var nsURI = customizationModel["FC_NsUri" + suffix] || null;
+        var nsPrefix = customizationModel["FC_NsPrefix" + suffix] || null;
+        var keepinContent = customizationModel["FC_KeepInContent" + suffix] || "";
+
+        if (targetPath !== targetXmlPath) {
+            nsURI = atomXmlNs;
+            nsPrefix = atomPrefix;
+        }
+
+        return {
+            contentKind: customizationModel["FC_ContentKind" + suffix],
+            keepInContent: keepinContent.toLowerCase() === "true",
+            nsPrefix: nsPrefix,
+            nsURI: nsURI,
+            propertyPath: propertyPath,
+            propertyType: propertyType,
+            entryPath: targetXmlPath
+        };
+    };
+
+    var atomApplyAllFeedCustomizations = function (entityType, model, callback) {
+        /// <summary>Gets all the feed customizations that have to be applied to an entry as per the enity type declared in an OData conceptual schema.</summary>
+        /// <param name="entityType" type="Object">Object describing an entity type in a conceptual schema.</param>
+        /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
+        /// <param name="callback" type="Function">Callback function to be invoked for each feed customization that needs to be applied.</param>
+
+        var customizations = [];
+        while (entityType) {
+            var sourcePath = entityType.FC_SourcePath;
+            var customization = atomFeedCustomization(entityType, entityType, model);
+            if (customization) {
+                callback(customization);
+            }
+
+            var properties = entityType.property || [];
+            var i, len;
+            for (i = 0, len = properties.length; i < len; i++) {
+                var property = properties[i];
+                var suffixCounter = 0;
+                var suffix = "";
+
+                while (customization = atomFeedCustomization(property, entityType, model, property.name, suffix)) {
+                    callback(customization);
+                    suffixCounter++;
+                    suffix = "_" + suffixCounter;
+                }
+            }
+            entityType = lookupEntityType(entityType.baseType, model);
+        }
+        return customizations;
+    };
+
+    var atomReadExtensionAttributes = function (domElement) {
+        /// <summary>Reads ATOM extension attributes (any attribute not in the Atom namespace) from a DOM element.</summary>
+        /// <param name="domElement">DOM element with zero or more extension attributes.</param>
+        /// <returns type="Array">An array of extension attribute representations.</returns>
+
+        var extensions = [];
+        xmlAttributes(domElement, function (attribute) {
+            var nsURI = xmlNamespaceURI(attribute);
+            if (isExtensionNs(nsURI)) {
+                extensions.push(createAttributeExtension(attribute, true));
+            }
+        });
+        return extensions;
+    };
+
+    var atomReadExtensionElement = function (domElement) {
+        /// <summary>Reads an ATOM extension element (an element not in the ATOM namespaces).</summary>
+        /// <param name="domElement">DOM element not part of the atom namespace.</param>
+        /// <returns type="Object">Object representing the extension element.</returns>
+
+        return createElementExtension(domElement, /*addNamespaceURI*/true);
+    };
+
+    var atomReadDocument = function (domElement, baseURI, model) {
+        /// <summary>Reads an ATOM entry, feed or service document, producing an object model in return.</summary>
+        /// <param name="domElement">Top-level ATOM DOM element to read.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM document.</param>
+        /// <param name="model" type="Object">Object that describes the conceptual schema.</param>
+        /// <returns type="Object">The object model representing the specified element, undefined if the top-level element is not part of the ATOM specification.</returns>
+
+        var nsURI = xmlNamespaceURI(domElement);
+        var localName = xmlLocalName(domElement);
+
+        // Handle service documents.
+        if (nsURI === appXmlNs && localName === "service") {
+            return atomReadServiceDocument(domElement, baseURI);
+        }
+
+        // Handle feed and entry elements.
+        if (nsURI === atomXmlNs) {
+            if (localName === "feed") {
+                return atomReadFeed(domElement, baseURI, model);
+            }
+            if (localName === "entry") {
+                return atomReadEntry(domElement, baseURI, model);
+            }
+        }
+
+        // Allow undefined to be returned.
+    };
+
+    var atomReadAdvertisedActionOrFunction = function (domElement, baseURI) {
+        /// <summary>Reads the DOM element for an action or a function in an OData Atom document.</summary>
+        /// <param name="domElement">DOM element to read.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing the action or function target url.</param>
+        /// <returns type="Object">Object with title, target, and metadata fields.</returns>
+
+        var extensions = [];
+        var result = { extensions: extensions };
+        xmlAttributes(domElement, function (attribute) {
+            var localName = xmlLocalName(attribute);
+            var nsURI = xmlNamespaceURI(attribute);
+            var value = xmlNodeValue(attribute);
+
+            if (nsURI === null) {
+                if (localName === "title" || localName === "metadata") {
+                    result[localName] = value;
+                    return;
+                }
+                if (localName === "target") {
+                    result.target = normalizeURI(value, xmlBaseURI(domElement, baseURI));
+                    return;
+                }
+            }
+
+            if (isExtensionNs(nsURI)) {
+                extensions.push(createAttributeExtension(attribute, true));
+            }
+        });
+        return result;
+    };
+
+    var atomReadAdvertisedAction = function (domElement, baseURI, parentMetadata) {
+        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
+        /// <param name="domElement">DOM element to read.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
+        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
+
+        var actions = parentMetadata.actions = parentMetadata.actions || [];
+        actions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
+    };
+
+    var atomReadAdvertisedFunction = function (domElement, baseURI, parentMetadata) {
+        /// <summary>Reads the DOM element for an action in an OData Atom document.</summary>
+        /// <param name="domElement">DOM element to read.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing the action or target url.</param>
+        /// <param name="parentMetadata" type="Object">Object to update with the action metadata.</param>
+
+        var functions = parentMetadata.functions = parentMetadata.functions || [];
+        functions.push(atomReadAdvertisedActionOrFunction(domElement, baseURI));
+    };
+
+    var atomReadFeed = function (domElement, baseURI, model) {
+        /// <summary>Reads a DOM element for an ATOM feed, producing an object model in return.</summary>
+        /// <param name="domElement">ATOM feed DOM element.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the ATOM feed.</param>
+        /// <param name="model">Metadata that describes the conceptual schema.</param>
+        /// <returns type="Object">A new object representing the feed.</returns>
+
+        var extensions = atomReadExtensionAttributes(domElement);
+        var feedMetadata = { feed_extensions: extensions };
+        var results = [];
+
+        var feed = { __metadata: feedMetadata, results: results };
+
+        baseURI = xmlBaseURI(domElement, baseURI);
+
+        xmlChildElements(domElement, function (child) {
+            var nsURI = xmlNamespaceURI(child);
+            var localName = xmlLocalName(child);
+
+            if (nsURI === odataMetaXmlNs) {
+                if (localName === "count") {
+                    feed.__count = parseInt(xmlInnerText(child), 10);
+                    return;
+                }
+                if (localName === "action") {
+                    atomReadAdvertisedAction(child, baseURI, feedMetadata);
+                    return;
+                }
+                if (localName === "function") {
+                    atomReadAdvertisedFunction(child, baseURI, feedMetadata);
+                    return;
+                }
+            }
+
+            if (isExtensionNs(nsURI)) {
+                extensions.push(createElementExtension(child));
+                return;
+            }
+
+            // The element should belong to the ATOM namespace.
+            djsassert(nsURI === atomXmlNs, "atomReadFeed - child feed element is not in the atom namespace!!");
+
+            if (localName === "entry") {
+                results.push(atomReadEntry(child, baseURI, model));
+                return;
+            }
+            if (localName === "link") {
+                atomReadFeedLink(child, feed, baseURI);
+                return;
+            }
+            if (localName === "id") {
+                feedMetadata.uri = normalizeURI(xmlInnerText(child), baseURI);
+                feedMetadata.uri_extensions = atomReadExtensionAttributes(child);
+                return;
+            }
+            if (localName === "title") {
+                feedMetadata.title = xmlInnerText(child) || "";
+                feedMetadata.title_extensions = atomReadExtensionAttributes(child);
+                return;
+            }
+        });
+
+        return feed;
+    };
+
+    var atomReadFeedLink = function (domElement, feed, baseURI) {
+        /// <summary>Reads an ATOM link DOM element for a feed.</summary>
+        /// <param name="domElement">ATOM link DOM element.</param>
+        /// <param name="feed">Feed object to be annotated with the link data.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing relative URIs found in the payload.</param>
+
+        var link = atomReadLink(domElement, baseURI);
+        var href = link.href;
+        var rel = link.rel;
+        var extensions = link.extensions;
+        var metadata = feed.__metadata;
+
+        if (rel === "next") {
+            feed.__next = href;
+            metadata.next_extensions = extensions;
+            return;
+        }
+        if (rel === "self") {
+            metadata.self = href;
+            metadata.self_extensions = extensions;
+            return;
+        }
+    };
+
+    var atomReadLink = function (domElement, baseURI) {
+        /// <summary>Reads an ATOM link DOM element.</summary>
+        /// <param name="linkElement">DOM element to read.</param>
+        /// <param name="baseURI" type="String">Base URI for normalizing the link href.</param>
+        /// <returns type="Object">A link element representation.</returns>
+
+        baseURI = xmlBaseURI(domElement, baseURI);
+
+        var extensions = [];
+        var link = { extensions: extensions, baseURI: baseURI };
+
+        xmlAttributes(domElement, function (attribute) {
+            var nsURI = xmlNamespaceURI(attribute);
+            var localName = xmlLocalName(attribute);
+            var value = a

<TRUNCATED>