| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Globalization;
 
- using System.Linq;
 
- using System.Xml;
 
- using Jellyfin.Data.Enums;
 
- using MediaBrowser.Controller.Entities;
 
- namespace MediaBrowser.Controller.Extensions;
 
- /// <summary>
 
- /// Provides extension methods for <see cref="XmlReader"/> to parse <see cref="BaseItem"/>'s.
 
- /// </summary>
 
- public static class XmlReaderExtensions
 
- {
 
-     /// <summary>
 
-     /// Reads a trimmed string from the current node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <returns>The trimmed content.</returns>
 
-     public static string ReadNormalizedString(this XmlReader reader)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         return reader.ReadElementContentAsString().Trim();
 
-     }
 
-     /// <summary>
 
-     /// Reads an int from the current node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <param name="value">The parsed <c>int</c>.</param>
 
-     /// <returns>A value indicating whether the parsing succeeded.</returns>
 
-     public static bool TryReadInt(this XmlReader reader, out int value)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         return int.TryParse(reader.ReadElementContentAsString(), CultureInfo.InvariantCulture, out value);
 
-     }
 
-     /// <summary>
 
-     /// Parses a <see cref="DateTime"/> from the current node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <param name="value">The parsed <see cref="DateTime"/>.</param>
 
-     /// <returns>A value indicating whether the parsing succeeded.</returns>
 
-     public static bool TryReadDateTime(this XmlReader reader, out DateTime value)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         return DateTime.TryParse(
 
-             reader.ReadElementContentAsString(),
 
-             CultureInfo.InvariantCulture,
 
-             DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
 
-             out value);
 
-     }
 
-     /// <summary>
 
-     /// Parses a <see cref="DateTime"/> from the current node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <param name="formatString">The date format string.</param>
 
-     /// <param name="value">The parsed <see cref="DateTime"/>.</param>
 
-     /// <returns>A value indicating whether the parsing succeeded.</returns>
 
-     public static bool TryReadDateTimeExact(this XmlReader reader, string formatString, out DateTime value)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         ArgumentNullException.ThrowIfNull(formatString);
 
-         return DateTime.TryParseExact(
 
-             reader.ReadElementContentAsString(),
 
-             formatString,
 
-             CultureInfo.InvariantCulture,
 
-             DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
 
-             out value);
 
-     }
 
-     /// <summary>
 
-     /// Parses a <see cref="PersonInfo"/> from the xml node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <returns>A <see cref="PersonInfo"/>, or <c>null</c> if none is found.</returns>
 
-     public static PersonInfo? GetPersonFromXmlNode(this XmlReader reader)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         if (reader.IsEmptyElement)
 
-         {
 
-             reader.Read();
 
-             return null;
 
-         }
 
-         var name = string.Empty;
 
-         var type = PersonKind.Actor;  // If type is not specified assume actor
 
-         var role = string.Empty;
 
-         int? sortOrder = null;
 
-         string? imageUrl = null;
 
-         using var subtree = reader.ReadSubtree();
 
-         subtree.MoveToContent();
 
-         subtree.Read();
 
-         while (subtree is { EOF: false, ReadState: ReadState.Interactive })
 
-         {
 
-             if (subtree.NodeType != XmlNodeType.Element)
 
-             {
 
-                 subtree.Read();
 
-                 continue;
 
-             }
 
-             switch (subtree.Name)
 
-             {
 
-                 case "name":
 
-                 case "Name":
 
-                     name = subtree.ReadNormalizedString();
 
-                     break;
 
-                 case "role":
 
-                 case "Role":
 
-                     role = subtree.ReadNormalizedString();
 
-                     break;
 
-                 case "type":
 
-                 case "Type":
 
-                     Enum.TryParse(subtree.ReadElementContentAsString(), true, out type);
 
-                     break;
 
-                 case "order":
 
-                 case "sortorder":
 
-                 case "SortOrder":
 
-                     if (subtree.TryReadInt(out var sortOrderVal))
 
-                     {
 
-                         sortOrder = sortOrderVal;
 
-                     }
 
-                     break;
 
-                 case "thumb":
 
-                     imageUrl = subtree.ReadNormalizedString();
 
-                     break;
 
-                 default:
 
-                     subtree.Skip();
 
-                     break;
 
-             }
 
-         }
 
-         if (string.IsNullOrWhiteSpace(name))
 
-         {
 
-             return null;
 
-         }
 
-         return new PersonInfo
 
-         {
 
-             Name = name,
 
-             Role = role,
 
-             Type = type,
 
-             SortOrder = sortOrder,
 
-             ImageUrl = imageUrl
 
-         };
 
-     }
 
-     /// <summary>
 
-     /// Used to split names of comma or pipe delimited genres and people.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <returns>IEnumerable{System.String}.</returns>
 
-     public static IEnumerable<string> GetStringArray(this XmlReader reader)
 
-     {
 
-         ArgumentNullException.ThrowIfNull(reader);
 
-         var value = reader.ReadElementContentAsString();
 
-         // Only split by comma if there is no pipe in the string
 
-         // We have to be careful to not split names like Matthew, Jr.
 
-         var separator = !value.Contains('|', StringComparison.Ordinal)
 
-             && !value.Contains(';', StringComparison.Ordinal)
 
-                 ? new[] { ',' }
 
-                 : new[] { '|', ';' };
 
-         foreach (var part in value.Trim().Trim(separator).Split(separator))
 
-         {
 
-             if (!string.IsNullOrWhiteSpace(part))
 
-             {
 
-                 yield return part.Trim();
 
-             }
 
-         }
 
-     }
 
-     /// <summary>
 
-     /// Parses a <see cref="PersonInfo"/> array from the xml node.
 
-     /// </summary>
 
-     /// <param name="reader">The <see cref="XmlReader"/>.</param>
 
-     /// <param name="personKind">The <see cref="PersonKind"/>.</param>
 
-     /// <returns>The <see cref="IEnumerable{PersonInfo}"/>.</returns>
 
-     public static IEnumerable<PersonInfo> GetPersonArray(this XmlReader reader, PersonKind personKind)
 
-         => reader.GetStringArray()
 
-             .Select(part => new PersonInfo { Name = part, Type = personKind });
 
- }
 
 
  |