Link to home
Start Free TrialLog in
Avatar of trevor1940
trevor1940

asked on

C#: Reading and appending XML file using LINQ with nested values

Hi This is following on from here

As a learning exercise I'm retrieving and updating an XML file of TV show  information  

It occurred to me that it's possible to have multiple seasons to the same TV show so I adjusted the XML accordingly
TV.XML
<?xml version="1.0"?>
<TV>
  <Show>
      <Name>MacGyver 2016</Name>
      <FolderName>MacGyver 2016</FolderName>
      <TMDBid>67133</TMDBid>
      <Season>
        <SeasonNumber>3</SeasonNumber>
        <Episode>
          <EpisodeNumber>1</EpisodeNumber>
          <EpisodeName>Improvise</EpisodeName>
          <BackDrop>https://image.tmdb.org/t/p/w350_and_h196_bestv2/eQMVJkBltvID73sh9vvTistssS6.jpg</BackDrop>
          <FullPath>J:\Media\TV\MacGyver (2016)\S03\Macgyver.2016.S03E01.Improvise.mp4</FullPath>
        </Episode>
      </Season>
      
  </Show>
</TV>

Open in new window


Of course this broke the LINQ query from the previous so answer

How do adjust the select query bellow to retrieve Episode data which is now nested in Season?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace XmlReader
{
    class Program
    {
        static void Main(string[] args)
        {
            // Load the XML Document using Linq to XML
            var xdoc = XDocument.Load(@"J:\Media\TV\TV.xml");
            // Query the Document for the Show's
            var shows = (from node in xdoc.Descendants("Show")
                         select new
                         {
                             ShowName = node.Element("Name").Value,
                             TMDBid = node.Element("TMDBid").Value,
                             Season = node.Elements("Season").Select(sn => new
                             {
                                 SeasonNumber = sn.Element("SeasonNumber").Value,
                                 Episode = sn.Elements("Episode").Select(ep => new
                                 {
                                     EpisodeNumber = ep.Element("EpisodeNumber").Value,
                                     EpisodeName = ep.Element("EpisodeName").Value,
                                     BackDrop = ep.Element("BackDrop").Value,
                                     FullPath = ep.Element("FullPath").Value
                                 })
                             }).ToList()
                         });

            foreach (var item in shows)
            {
                Console.WriteLine("Show Name: {0}", item.ShowName);
                foreach (var ep in item.Season )
                {
                    Console.WriteLine("\tSeasonNumber: {0}\nEpisodeNumber: {1}, EpisodeName: {2},\nBackDrop: {3}, \nFullPath: {4} ",
                       ep.SeasonNumber, ep.EpisodeNumber, ep.EpisodeName, ep.BackDrop, ep.FullPath);
                }
            }
            Console.ReadLine();
        }// end main
    }
}

Open in new window

Searching google just got me more  confused

Clearly I'll also need to adjust the Update and how  to see if a show or episode exists?
ASKER CERTIFIED SOLUTION
Avatar of Fernando Soto
Fernando Soto
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of trevor1940
trevor1940

ASKER

Hi Building on the above and in the last question about checking if a show exist i've re writen your code

        private static bool CheckShow(string showname, string season, string episode)
        {
            // // Checks for the existence of a Show Season and Episode
            var results = (from node in xdoc.Descendants("Show")
                           where node.Element("Name").Value == showname &&
                                 node.Element("Season").Element("SeasonNumber").Value == season &&
                                  node.Element("Season").Element("Episode").Element("EpisodeNumber").Value == episode // This looks cumbersome
                           select node).FirstOrDefault();
            return results != null ? true : false;
        }

Open in new window

It seems to work but Is this the best way to check for nested elements as it  looks cumbersome
Hi trevor1940;

It may look cumbersome but it is a helper function so you only write it once and use it from anywhere. It is this way because the information comes from different levels of the document and therefor you need to access those levels to get the data.
Thank You

Although beyond the scope of what I'm currently doing the information you provided has made me think about how to deal with more  complex XML file containing namespaces & attributions
I'm sure I'll need this again

Thanx