af1152b001
Refactored all C# test files to use explicit namespace declarations and moved all using directives inside the namespace block for consistency. Updated assembly info and cache files to reflect the new build. Adjusted MvcTestingAppManifest.json to use fully qualified assembly names. No functional changes; all updates are related to code style, organization, and project metadata.
198 lines
6.8 KiB
C#
198 lines
6.8 KiB
C#
// <copyright file="XmlReaderExtensions.cs" company="PlaceholderCompany">
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace MediaBrowser.Controller.Extensions;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using Jellyfin.Data.Enums;
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
/// <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.
|
|
ReadOnlySpan<char> separator = !value.Contains('|', StringComparison.Ordinal)
|
|
&& !value.Contains(';', StringComparison.Ordinal)
|
|
? stackalloc[] { ',' }
|
|
: stackalloc[] { '|', ';' };
|
|
|
|
foreach (var part in value.AsSpan().Trim().Trim(separator).ToString().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 });
|
|
}
|