Inheritance: XmlReader, IXmlLineInfo
Esempio n. 1
0
        /// <summary>
        /// read the m2:count tag in the feed
        /// </summary>
        private void ReadCountValue()
        {
            Debug.Assert(this.countValue == CountStateInitial, "Count value is not in the initial state");

            if (this.CurrentFeed != null &&
                this.CurrentFeed.Count.HasValue)
            {
                this.countValue = this.CurrentFeed.Count.Value;
                return;
            }

            // find the first element tag
            while (this.reader.NodeType != XmlNodeType.Element && this.reader.Read())
            {
            }

            if (this.reader.EOF)
            {
                throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent);
            }

            // the tag Should only be <feed> or <links> tag:
            Debug.Assert(
                (Util.AreSame(XmlConstants.AtomNamespace, this.reader.NamespaceURI) &&
                Util.AreSame(XmlConstants.AtomFeedElementName, this.reader.LocalName)) ||
                (Util.AreSame(XmlConstants.DataWebNamespace, this.reader.NamespaceURI) &&
                Util.AreSame(XmlConstants.LinkCollectionElementName, this.reader.LocalName)),
                "<feed> or <links> tag expected");

            // Create the XElement for look-ahead
            // DEVNOTE(pqian):
            // This is not streaming friendly!
            XElement element = XElement.Load(this.reader);
            this.reader.Close();

            // Read the count value from the xelement
            XElement countNode = element.Descendants(XNamespace.Get(XmlConstants.DataWebMetadataNamespace) + XmlConstants.RowCountElement).FirstOrDefault();

            if (countNode == null)
            {
                throw new InvalidOperationException(Strings.MaterializeFromAtom_CountNotPresent);
            }
            else
            {
                if (!long.TryParse(countNode.Value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out this.countValue))
                {
                    throw new FormatException(Strings.MaterializeFromAtom_CountFormatError);
                }
            }

            this.reader = new Microsoft.OData.Service.Client.Xml.XmlAtomErrorReader(element.CreateReader());
        }
Esempio n. 2
0
        /// <summary>Initializes a new <see cref="AtomParser"/> instance.</summary>
        /// <param name="reader"><see cref="XmlReader"/> to parse content from.</param>
        /// <param name="entryCallback">
        /// Callback invoked each time an ATOM entry is found; see the comments
        /// on the entryCallback field.
        /// </param>
        /// <param name="typeScheme">
        /// Scheme used to find type information on ATOM category elements.
        /// </param>
        /// <param name="currentDataNamespace">The xml document's DataWeb Namespace</param>
        /// <param name="baseUriResolver">Interface to retrieve the baseUri to use for this EntitySetName - this will be used to convert relative uri's in the response payload to absolute uri's.</param>
        /// <param name="maxProtocolVersion">max protocol version that the client understands.</param>
        internal AtomParser(XmlReader reader, Func<XmlWrappingReader, KeyValuePair<XmlWrappingReader, AtomTag>> entryCallback, string typeScheme, string currentDataNamespace, UriResolver baseUriResolver, DataServiceProtocolVersion maxProtocolVersion)
        {
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(typeScheme != null, "typeScheme != null");
            Debug.Assert(entryCallback != null, "entryCallback != null");
            Debug.Assert(!String.IsNullOrEmpty(currentDataNamespace), "currentDataNamespace is empty or null");
            Debug.Assert(baseUriResolver != null, "baseUriResolver != null");

            if (reader.Settings.NameTable != null)
            {
                // NOTE: dataNamespace is used for reference equality, and while it looks like
                // a variable, it appears that it will only get set to XmlConstants.DataWebNamespace
                // at runtime. Therefore we remove string dataNamespace as a field here.
                // this.dataNamespace = reader != null ? reader.Settings.NameTable.Add(context.DataNamespace) : null;
                reader.Settings.NameTable.Add(currentDataNamespace);
            }

            this.reader = new Microsoft.OData.Service.Client.Xml.XmlAtomErrorReader(reader);
            this.readers = new Stack<XmlWrappingReader>();
            this.entryCallback = entryCallback;
            this.typeScheme = typeScheme;
            this.currentDataNamespace = currentDataNamespace;
            this.baseUriResolver = baseUriResolver;
            this.countValue = CountStateInitial;
            this.MaxProtocolVersion = maxProtocolVersion;
            Debug.Assert(this.kind == AtomDataKind.None, "this.kind == AtomDataKind.None -- otherwise not initialized correctly");
        }
Esempio n. 3
0
        internal static KeyValuePair<XmlWrappingReader, AtomTag> XElementBuilderCallback(XmlWrappingReader reader)
        {
            Debug.Assert(reader != null, "reader != null");

            XElement element = XElement.Load(reader.ReadSubtree(), LoadOptions.None);

            // The XElement created here will be passed to users through the DataServiceContext.ReadingEntity event.  If xml:base is on the parent
            // element, there is no way to get to the base uri from the event handler.  Links in the atom payload are relative uris, we are storing the
            // xml base in the tag and pass it to ReadingWritingEntityEventArgs.BaseUri so the full uris for links can be constructed.
            //
            // ReadingWritingEntityEventArgs.BaseUri contains the base uri from the current element.  If the current XElement also contains a xml:base
            // attribute, it will be part of the uri we are passing to ReadingWritingEntityEventArgs.BaseUri.
            //
            // [Client-ODataLib-Integration] ReadingEntityEvent in astoria client gives the incorrect base uri in the event args
            // We will pass in the base uri of the parent element to the readingentity event.
            AtomTag tag = new AtomTag(element, reader.ParentBaseURI);

            return new KeyValuePair<XmlWrappingReader, AtomTag>(XmlWrappingReader.CreateReader(reader.ParentBaseURI, element.CreateReader()), tag);
        }
Esempio n. 4
0
        /// <summary>
        /// Parses the current reader into a new <paramref name="targetEntry"/> 
        /// instance.
        /// </summary>
        /// <param name="targetEntry">
        /// After invocation, the target entry that was created as a result
        /// of parsing the current reader.
        /// </param>
        private void ParseCurrentEntry(out AtomEntry targetEntry)
        {
            Debug.Assert(this.reader.NodeType == XmlNodeType.Element, "this.reader.NodeType == XmlNodeType.Element");

            // Push reader.
            var callbackResult = this.entryCallback(this.reader);
            Debug.Assert(callbackResult.Key != null, "callbackResult.Key != null");
            this.readers.Push(this.reader);
            this.reader = callbackResult.Key;

            this.reader.Read();
            Debug.Assert(this.reader.LocalName == "entry", "this.reader.LocalName == 'entry' - otherwise we're not reading the subtree");

            targetEntry = new AtomEntry(this.MaxProtocolVersion);
            targetEntry.DataValues = new List<AtomContentProperty>();
            targetEntry.Tag = callbackResult.Value;
            targetEntry.EntityDescriptor.ETag = this.reader.GetAttribute(XmlConstants.AtomETagAttributeName, XmlConstants.DataWebMetadataNamespace);

            while (this.reader.Read())
            {
                if (ShouldIgnoreNode(this.reader))
                {
                    continue;
                }

                if (this.reader.NodeType == XmlNodeType.Element)
                {
                    int depth = this.reader.Depth;
                    string elementName = this.reader.LocalName;
                    string namespaceURI = this.reader.NamespaceURI;
                    if (namespaceURI == XmlConstants.AtomNamespace)
                    {
                        if (elementName == XmlConstants.AtomCategoryElementName && targetEntry.TypeName == null)
                        {
                            string text = this.reader.GetAttributeEx(XmlConstants.AtomCategorySchemeAttributeName, XmlConstants.AtomNamespace);
                            if (text == this.typeScheme && !targetEntry.TypeNameHasBeenSet)
                            {
                                targetEntry.TypeNameHasBeenSet = true;
                                targetEntry.TypeName = this.reader.GetAttributeEx(XmlConstants.AtomCategoryTermAttributeName, XmlConstants.AtomNamespace);
                            }
                        }
                        else if (elementName == XmlConstants.AtomContentElementName)
                        {
                            this.ParseCurrentContent(targetEntry);
                        }
                        else if (elementName == XmlConstants.AtomIdElementName && targetEntry.Identity == null)
                        {
                            // The .Identity == null check ensures that only the first id element is processed.
                            string idText = ReadElementStringForText(this.reader);
                            WebUtil.ValidateIdentityValue(idText);
                            targetEntry.Identity = idText;
                        }
                        else if (elementName == XmlConstants.AtomLinkElementName)
                        {
                            this.ParseCurrentLink(targetEntry);
                        }
                    }
                    else if (namespaceURI == XmlConstants.DataWebMetadataNamespace)
                    {
                        if (elementName == XmlConstants.AtomPropertiesElementName)
                        {
                            if (targetEntry.MediaLinkEntry.HasValue && !targetEntry.MediaLinkEntry.Value)
                            {
                                // This means we saw a non-empty <atom:Content> element but now we have a Properties element
                                // that also carries properties
                                throw Error.InvalidOperation(Strings.Deserialize_ContentPlusPropertiesNotAllowed);
                            }

                            targetEntry.MediaLinkEntry = true;

                            if (!this.reader.IsEmptyElement)
                            {
                                this.ReadCurrentProperties(targetEntry.DataValues);
                            }
                        }
                        else if (elementName == XmlConstants.ActionElementName || elementName == XmlConstants.FunctionElementName)
                        {
                            this.ReadOperationDescriptor(targetEntry);
                        }
                    }

                    CommonUtil.SkipToEndAtDepth(this.reader, depth);
                }
            }

            if (targetEntry.Identity == null)
            {
                throw Error.InvalidOperation(Strings.Deserialize_MissingIdElement);
            }

            this.reader = this.readers.Pop();
        }