using System; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; using System.Xml; namespace MediaBrowser.Providers.TV { /// /// Class EpisodeXmlParser /// public class EpisodeXmlParser : BaseItemXmlParser { private readonly IItemRepository _itemRepo; private Task _chaptersTask = null; public EpisodeXmlParser(ILogger logger, IItemRepository itemRepo) : base(logger) { _itemRepo = itemRepo; } public async Task FetchAsync(Episode item, string metadataFile, CancellationToken cancellationToken) { _chaptersTask = null; Fetch(item, metadataFile, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); if (_chaptersTask != null) { await _chaptersTask.ConfigureAwait(false); } } private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// /// Fetches the data from XML node. /// /// The reader. /// The item. protected override void FetchDataFromXmlNode(XmlReader reader, Episode item) { switch (reader.Name) { case "Chapters": //_chaptersTask = FetchChaptersFromXmlNode(item, reader.ReadSubtree(), _itemRepo, CancellationToken.None); break; case "Episode": //MB generated metadata is within an "Episode" node using (var subTree = reader.ReadSubtree()) { subTree.MoveToContent(); // Loop through each element while (subTree.Read()) { if (subTree.NodeType == XmlNodeType.Element) { FetchDataFromXmlNode(subTree, item); } } } break; case "filename": { var filename = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(filename)) { // Strip off everything but the filename. Some metadata tools like MetaBrowser v1.0 will have an 'episodes' prefix // even though it's actually using the metadata folder. filename = Path.GetFileName(filename); var seasonFolder = Path.GetDirectoryName(item.Path); filename = Path.Combine(seasonFolder, "metadata", filename); if (File.Exists(filename)) { item.SetImagePath(ImageType.Primary, 0, filename); } } break; } case "SeasonNumber": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { int num; if (int.TryParse(number, out num)) { item.ParentIndexNumber = num; } } break; } case "EpisodeNumber": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { int num; if (int.TryParse(number, out num)) { item.IndexNumber = num; } } break; } case "EpisodeNumberEnd": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { int num; if (int.TryParse(number, out num)) { item.IndexNumberEnd = num; } } break; } case "absolute_number": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) { item.AbsoluteEpisodeNumber = rval; } } break; } case "DVD_episodenumber": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { float num; if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) { item.DvdEpisodeNumber = num; } } break; } case "DVD_season": { var number = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(number)) { float num; if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) { item.DvdSeasonNumber = Convert.ToInt32(num); } } break; } case "airsbefore_episode": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) { item.AirsBeforeEpisodeNumber = rval; } } break; } case "airsafter_season": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) { item.AirsAfterSeasonNumber = rval; } } break; } case "airsbefore_season": { var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val)) { int rval; // int.TryParse is local aware, so it can be probamatic, force us culture if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval)) { item.AirsBeforeSeasonNumber = rval; } } break; } case "EpisodeName": { var name = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(name)) { item.Name = name; } break; } default: base.FetchDataFromXmlNode(reader, item); break; } } } }