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;
///
/// Provides extension methods for to parse 's.
///
public static class XmlReaderExtensions
{
///
/// Parses a from the xml node.
///
/// The .
/// A , or null if none is found.
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.ReadElementContentAsString();
break;
case "role":
case "Role":
var roleValue = subtree.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(roleValue))
{
role = roleValue;
}
break;
case "type":
case "Type":
Enum.TryParse(subtree.ReadElementContentAsString(), true, out type);
break;
case "order":
case "sortorder":
case "SortOrder":
if (int.TryParse(
subtree.ReadElementContentAsString(),
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var intVal))
{
sortOrder = intVal;
}
break;
case "thumb":
var thumb = subtree.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(thumb))
{
imageUrl = thumb;
}
break;
default:
subtree.Skip();
break;
}
}
if (string.IsNullOrWhiteSpace(name))
{
return null;
}
return new PersonInfo
{
Name = name.Trim(),
Role = role,
Type = type,
SortOrder = sortOrder,
ImageUrl = imageUrl
};
}
///
/// Used to split names of comma or pipe delimited genres and people.
///
/// The .
/// IEnumerable{System.String}.
public static IEnumerable 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();
}
}
}
///
/// Parses a array from the xml node.
///
/// The .
/// The .
/// The .
public static IEnumerable GetPersonArray(this XmlReader reader, PersonKind personKind)
=> reader.GetStringArray()
.Select(part => new PersonInfo { Name = part, Type = personKind });
}