Exemplo n.º 1
0
        /// <summary>
        /// Create and Add Parse error to the current feed result.
        /// </summary>
        /// <param name="errorType">Type of parse error.</param>
        /// <param name="nodeInformation">Current node base information.</param>
        /// <param name="feed">Current feed result.</param>
        /// <param name="content">Current node content data. (Optonal)</param>
        /// <param name="message">Parse error message. (Optional)</param>
        protected void SetParseError(ParseErrorType errorType, NodeInformation nodeInformation, Feed feed, string?content = null, string?message = null)
        {
            //Create and Add Parse error to the current feed result
            var error = ParseError.Create(nodeInformation, ToString(), errorType, feed.CurrentParseType, content, message);

            (feed.ParseError ??= new List <ParseError>()).Add(error);
            Debug.WriteLine(error);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Main parse feed stream method.
        /// </summary>
        /// <param name="source">Feed source name/url.</param>
        /// <param name="stream">Feed stream.</param>
        /// <param name="cancellationToken">Parse task cancellation token.</param>
        /// <returns>The parsed feed result Feed object.</returns>
        public static async Task <Feed> ParseFeedAsync(string source, Stream stream, CancellationToken cancellationToken)
        {
            //Init
            bool parseNode;
            var  feed          = new Feed();
            var  defaultParser = RSS_2_0_Parser.Instance;
            var  settings      = new XmlReaderSettings()
            {
                CloseInput = true, ConformanceLevel = ConformanceLevel.Document, IgnoreWhitespace = true, IgnoreComments = true, Async = true, DtdProcessing = DtdProcessing.Ignore
            };

            using var reader = XmlReader.Create(stream, settings);

            try
            {
                //Start Reading and move to root node
                if (parseNode = await reader.MoveToContentAsync().ConfigureAwait(false) != XmlNodeType.None)
                {
                    //Save Parent Node
                    var parent = new Stack <NodeInformation>(new List <NodeInformation>()
                    {
                        reader.NodeInformation()
                    });

                    //Attempt to identify feed type
                    defaultParser = ParseFeedType(reader, feed) ?? defaultParser;

                    //Read first feed node
                    parseNode = await reader.ReadAsync().ConfigureAwait(false);

                    //Identify and parse nodes until EOF or Cancellation
                    while (parseNode && !reader.EOF && !cancellationToken.IsCancellationRequested)
                    {
                        //Feed node or Extended Namespace node?
                        if (string.IsNullOrWhiteSpace(reader.NamespaceURI))
                        {
                            //Parse node with default feed parser
                            await defaultParser.Value.Parse(parent, reader, feed).ConfigureAwait(false);
                        }
                        else if (parseNode = parsers.TryGetValue(reader.NamespaceURI, out var parser))
                        {
                            //Parse node with current Namespace parser
                            await parser.Value.Parse(parent, reader, feed).ConfigureAwait(false);
                        }
                        else
                        {
                            //Unknown Namespace
                            var error = ParseError.Create(reader.NodeInformation(), "FeedParser", ParseErrorType.UnknownNamespace, feed.CurrentParseType);
                            (feed.ParseError ??= new List <ParseError>()).Add(error);
                            Debug.WriteLine(error);
                        }

                        //Save Parent Node
                        if (reader.NodeType != XmlNodeType.EndElement && reader.Depth > (parent.Count > 0 ? parent.Peek().Depth : -1))
                        {
                            parent.Push(reader.NodeInformation());
                        }

                        //Read next node
                        parseNode = await reader.ReadAsync().ConfigureAwait(false);

                        //Verify Parent
                        while (parent.Count > 0 && reader.Depth <= parent.Peek().Depth)
                        {
                            parent.Pop();
                        }
                    }
                }
            }
            //Rethrow Feed Parser Exception
            catch (FeedParseException ex) { throw ex; }
            catch (Exception ex)
            {
                //Rethrow all other exceptions as FeedParseException
                throw new FeedParseException(source, reader, ex);
            }
            finally
            {
                //Close Reader and Stream
                reader?.Close();
            }

            //Return Parsed Feed
            return(feed);
        }