简体   繁体   中英

Reading XML ElementExtensions in C# Win8.1 App

I'm new to both C# and Windows App development, my comes experience mostly in python but I'm trying to challenge myself to learn something new.

I've been practicing/learning c# by making windows store apps, and after doing some WinJS/HTML5 tutorials I started on this tutorial: http://msdn.microsoft.com/en-us/library/windows/apps/br211380.aspx

I've completed the tutorial (including modifying the instructions for 8.1 apps since the tutorial is behind. I'm now trying to adapt my application to handle other types of data.

I'm attempting to pull all of the media:image tags from each item in a post so that I can display them. This is the structure of my XML data from an RSS feed.

        <item>
        <title>Post with photos</title>
        <link>http://website.com/2014/07/23/post-1//</link>
        <comments>http://website.com/2014/07/23/post-1/#comments</comments>
        <pubDate>Wed, 23 Jul 2014 15:45:02 +0000</pubDate>
        <dc:creator><![CDATA[Author]]></dc:creator>
                <category><![CDATA[Post]]></category>

        <guid isPermaLink="false">http://www.website.com/p?1</guid>
        <description><![CDATA[description here]]></description>
        <wfw:commentRss>http://www.website.com/post/1/feed/</wfw:commentRss>
        <slash:comments>0</slash:comments>
        <enclosure type="image/jpeg" length="1" url="http://0.gravatar.com/avatar/" />

        <media:thumbnail url="http://www.website.com/thumbnail_urle1406130272443.jpg?w=500" />
            <media:content url="http://0.gravatar.com/avatar/" medium="image">
            <media:category>author</media:category>
        </media:content>
            <media:content url="http://www.website.com/post/1/233-e1406130272443.jpg" medium="image">
            <media:title>image-23</media:title>
                    </media:content>
            <media:content url="http://www.website.com/post/1/163.jpg" medium="image">
            <media:title>image-16</media:title>
                    </media:content>
            <media:content url="http://www.website.com/post/1/73.jpg" medium="image">
            <media:title>bimage-7</media:title>
                    </media:content>
        </item>

I implemented this in HTML5/JS and when I did I used this method:

        var thumb = post.querySelector(
            "thumbnail").attributes.getNamedItem("url").textContent;
        var postImages = post.querySelectorAll("content");

        var ImageList = [];
        for (var imgIndex = 1; imgIndex < postImages.length; imgIndex++) {
            var imgHTML = "<img src='" + postImages[imgIndex].attributes.getNamedItem("url").textContent + "'</img><br/>";
            var ImageList = ImageList += imgHTML;
        }

But naturally.. that won't do in C#. I have looked at these thread in SO: Get media elements from RSS using SyndicationFeed as well as the one linked inside of it and they don't work for me. When I try to use var elements = rss.Feed.Items.SelectMany(s => s.ElementExtensions.Select(x => x.GetObject().Value));

I do not have a GetObject method available when I put it all together using my code. Here is my current Data model.

        private async Task<FeedData> GetFeedAsync(string feedUriString)
        {
            Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
            Uri feedUri = new Uri(feedUriString);

            try
            {
                SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);

                // This code is executed after RetrieveFeedAsync returns the SyndicationFeed.
                // Process the feed and copy the data you want into the FeedData and FeedItem classes. 
                FeedData feedData = new FeedData();

                if (feed.Title != null && feed.Title.Text != null)
                {
                    feedData.Title = feed.Title.Text;
                }
                if (feed.Subtitle != null && feed.Subtitle.Text != null)
                {
                    feedData.Description = feed.Subtitle.Text;
                }
                if (feed.Items != null && feed.Items.Count > 0)
                {
                    // Use the date of the latest post as the last updated date.
                    feedData.PubDate = feed.Items[0].PublishedDate.DateTime;

                    foreach (SyndicationItem item in feed.Items)
                    {
                        FeedItem feedItem = new FeedItem();
                        if (item.Title != null && item.Title.Text != null)
                        {
                            feedItem.Title = item.Title.Text;
                        }
                        if (item.PublishedDate != null)
                        {
                            feedItem.PubDate = item.PublishedDate.DateTime;
                        }
                        if (item.Authors != null && item.Authors.Count > 0)
                        {
                            feedItem.Author = item.Authors[0].Name.ToString();
                        }
                        // Handles RSS / Atom Feed differences..
                        if (feed.SourceFormat == SyndicationFormat.Atom10)
                        {
                            if (item.Content != null && item.Content.Text != null)
                            {
                                feedItem.Content = item.Content.Text;
                            }
                            if (item.Id != null)
                            {
                                feedItem.Link = new Uri(item.Id);
                            }
                        }
                        else if (feed.SourceFormat == SyndicationFormat.Rss20)
                        {
                            if (item.Summary != null && item.Summary.Text != null)
                            {
                                feedItem.Content = item.Summary.Text;
                            }
                            if (item.Links != null && item.Links.Count > 0)
                            {
                                feedItem.Link = item.Links[0].Uri;
                            }
                        }
                        feedData.Items.Add(feedItem);
                    }
                }
                return feedData;
            }
            catch (Exception)
            {
                return null;
            }
        }

I've tried setting breakpoints and looking at the item data in my RSS2.0 syndication handler, and I can see var media = item.ElementExtensions; has an accurate acount of all the element extensions in my post, and the title of them. (NodeName "content", NodeValue is the "title" from the element. but no URI for the url tag..)

I am looking for some way to integrate some way of getting these media:content, media thumbnail, etc, into a list so that I can assemble them and use them for HTML content later in my app.

Any advice would be appreciated!

edit:

More of my code..

 public class FeedData
    {
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime PubDate { get; set; }
        public Uri Image { get; set; }

        private List<FeedItem> _Items = new List<FeedItem>();
        public List<FeedItem> Items
        {
            get
            {
                return this._Items;
            }
        }

    }

    // Holds info for a single blog post
    public class FeedItem
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public string Content { get; set; }
        public DateTime PubDate { get; set; }
        public Uri Link { get; set; }
    }

    // Holds a collection of blog feeds (FeedData), and contains methods needed to retrieve
    // the feeds
    public class FeedDataSource
    {
        private ObservableCollection<FeedData> _Feeds = new ObservableCollection<FeedData>();
        public ObservableCollection<FeedData> Feeds
        {
            get
            {
                return this._Feeds;
            }
        }

        public async Task GetFeedsAsync()
        {
            Task<FeedData> feed1 =
                GetFeedAsync("http://url.com/feed");
            Task<FeedData> feed2 =
                GetFeedAsync("http://url.com/feed");
            ... 
            ...

            this.Feeds.Add(await feed1);
                ...
                ...
                ...
            this.Feeds.Add(await feed15);

        }

I'm not familiar with phone apps but you'd be putting this data into a repeater of some sort, data grid, etc., yes? Not being familiar with the Task generic object I'll still hazard a guess that you could use the C# key-value pair class with the List, then in this object in a Repeater, Grid, directly. I believe any object that implements IEnumerable (which List should) can be iterated over with a KeyValuePair

Let me know a bit more of what you want to do. It seems to me a

foreach KeyValuePair KVP in ListObject
{
   //Access KVP.key and values with your code here ...
}

A more clear example is using a KVP to iterate over a dictionary object:

    foreach (KeyValuePair<string, string> entry in dictTestEasement)
    {
        builder.RowFormat.Height = 0.2; //force row height by text font by setting height small
        builder.InsertCell();
        builder.Font.Bold = true;
        builder.InsertHtml(entry.Key);
        builder.Font.Bold = false;
        builder.InsertCell();
        builder.InsertHtml(entry.Value);
    }

The builder in this case is a global object for document construction (Aspose Words Object) -- it's constructing a Word document. Don't be thrown by it.

seems straightforward ... I've used such solutions before and believe that's what you're fishing for.

SyndicationItem has a GetXMLDocument method that takes a SourceFormat (like Rss20) and then generates an XML string that you can parse using GEtElementsByTagName (or ID). Once you have that you can iterate through duplicate tags in a loop and use Attributes.GetNamedItem() to grab named attributes of an XML tag. It seems that 'media' is lopped off when exploring the xml for media:content tags in Rss20 format, so all thats necessary is content to search for.

var allImages = item.GetXmlDocument(feed.SourceFormat).GetElementsByTagName("content");
foreach (var s in allImages)
{
Debug.WriteLine(s.Attributes.GetNamedItem("url").InnerText;)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM