< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Extensions.XmlReaderExtensions
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs
Line coverage
93%
Covered lines: 56
Uncovered lines: 4
Coverable lines: 60
Total lines: 193
Line coverage: 93.3%
Branch coverage
60%
Covered branches: 39
Total branches: 64
Branch coverage: 60.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ReadNormalizedString(...)100%11100%
TryReadInt(...)100%11100%
TryReadDateTime(...)100%11100%
TryReadDateTimeExact(...)100%11100%
GetPersonFromXmlNode(...)60.93%68.16490%
GetPersonArray(...)100%11100%

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Extensions/XmlReaderExtensions.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Globalization;
 4using System.Linq;
 5using System.Xml;
 6using Jellyfin.Data.Enums;
 7using MediaBrowser.Controller.Entities;
 8
 9namespace MediaBrowser.Controller.Extensions;
 10
 11/// <summary>
 12/// Provides extension methods for <see cref="XmlReader"/> to parse <see cref="BaseItem"/>'s.
 13/// </summary>
 14public static class XmlReaderExtensions
 15{
 16    /// <summary>
 17    /// Reads a trimmed string from the current node.
 18    /// </summary>
 19    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 20    /// <returns>The trimmed content.</returns>
 21    public static string ReadNormalizedString(this XmlReader reader)
 22    {
 22423        ArgumentNullException.ThrowIfNull(reader);
 24
 22425        return reader.ReadElementContentAsString().Trim();
 26    }
 27
 28    /// <summary>
 29    /// Reads an int from the current node.
 30    /// </summary>
 31    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 32    /// <param name="value">The parsed <c>int</c>.</param>
 33    /// <returns>A value indicating whether the parsing succeeded.</returns>
 34    public static bool TryReadInt(this XmlReader reader, out int value)
 35    {
 8836        ArgumentNullException.ThrowIfNull(reader);
 37
 8838        return int.TryParse(reader.ReadElementContentAsString(), CultureInfo.InvariantCulture, out value);
 39    }
 40
 41    /// <summary>
 42    /// Parses a <see cref="DateTime"/> from the current node.
 43    /// </summary>
 44    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 45    /// <param name="value">The parsed <see cref="DateTime"/>.</param>
 46    /// <returns>A value indicating whether the parsing succeeded.</returns>
 47    public static bool TryReadDateTime(this XmlReader reader, out DateTime value)
 48    {
 949        ArgumentNullException.ThrowIfNull(reader);
 50
 951        return DateTime.TryParse(
 952            reader.ReadElementContentAsString(),
 953            CultureInfo.InvariantCulture,
 954            DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
 955            out value);
 56    }
 57
 58    /// <summary>
 59    /// Parses a <see cref="DateTime"/> from the current node.
 60    /// </summary>
 61    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 62    /// <param name="formatString">The date format string.</param>
 63    /// <param name="value">The parsed <see cref="DateTime"/>.</param>
 64    /// <returns>A value indicating whether the parsing succeeded.</returns>
 65    public static bool TryReadDateTimeExact(this XmlReader reader, string formatString, out DateTime value)
 66    {
 2067        ArgumentNullException.ThrowIfNull(reader);
 2068        ArgumentNullException.ThrowIfNull(formatString);
 69
 2070        return DateTime.TryParseExact(
 2071            reader.ReadElementContentAsString(),
 2072            formatString,
 2073            CultureInfo.InvariantCulture,
 2074            DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
 2075            out value);
 76    }
 77
 78    /// <summary>
 79    /// Parses a <see cref="PersonInfo"/> from the xml node.
 80    /// </summary>
 81    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 82    /// <returns>A <see cref="PersonInfo"/>, or <c>null</c> if none is found.</returns>
 83    public static PersonInfo? GetPersonFromXmlNode(this XmlReader reader)
 84    {
 5585        ArgumentNullException.ThrowIfNull(reader);
 86
 5587        if (reader.IsEmptyElement)
 88        {
 089            reader.Read();
 090            return null;
 91        }
 92
 5593        var name = string.Empty;
 5594        var type = PersonKind.Actor;  // If type is not specified assume actor
 5595        var role = string.Empty;
 5596        int? sortOrder = null;
 5597        string? imageUrl = null;
 98
 5599        using var subtree = reader.ReadSubtree();
 55100        subtree.MoveToContent();
 55101        subtree.Read();
 102
 623103        while (subtree is { EOF: false, ReadState: ReadState.Interactive })
 104        {
 568105            if (subtree.NodeType != XmlNodeType.Element)
 106            {
 339107                subtree.Read();
 339108                continue;
 109            }
 110
 229111            switch (subtree.Name)
 112            {
 113                case "name":
 114                case "Name":
 55115                    name = subtree.ReadNormalizedString();
 55116                    break;
 117                case "role":
 118                case "Role":
 54119                    role = subtree.ReadNormalizedString();
 54120                    break;
 121                case "type":
 122                case "Type":
 11123                    Enum.TryParse(subtree.ReadElementContentAsString(), true, out type);
 11124                    break;
 125                case "order":
 126                case "sortorder":
 127                case "SortOrder":
 55128                    if (subtree.TryReadInt(out var sortOrderVal))
 129                    {
 55130                        sortOrder = sortOrderVal;
 131                    }
 132
 55133                    break;
 134                case "thumb":
 54135                    imageUrl = subtree.ReadNormalizedString();
 54136                    break;
 137                default:
 0138                    subtree.Skip();
 139                    break;
 140            }
 141        }
 142
 55143        if (string.IsNullOrWhiteSpace(name))
 144        {
 0145            return null;
 146        }
 147
 55148        return new PersonInfo
 55149        {
 55150            Name = name,
 55151            Role = role,
 55152            Type = type,
 55153            SortOrder = sortOrder,
 55154            ImageUrl = imageUrl
 55155        };
 55156    }
 157
 158    /// <summary>
 159    /// Used to split names of comma or pipe delimited genres and people.
 160    /// </summary>
 161    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 162    /// <returns>IEnumerable{System.String}.</returns>
 163    public static IEnumerable<string> GetStringArray(this XmlReader reader)
 164    {
 165        ArgumentNullException.ThrowIfNull(reader);
 166        var value = reader.ReadElementContentAsString();
 167
 168        // Only split by comma if there is no pipe in the string
 169        // We have to be careful to not split names like Matthew, Jr.
 170        var separator = !value.Contains('|', StringComparison.Ordinal)
 171            && !value.Contains(';', StringComparison.Ordinal)
 172                ? new[] { ',' }
 173                : new[] { '|', ';' };
 174
 175        foreach (var part in value.Trim().Trim(separator).Split(separator))
 176        {
 177            if (!string.IsNullOrWhiteSpace(part))
 178            {
 179                yield return part.Trim();
 180            }
 181        }
 182    }
 183
 184    /// <summary>
 185    /// Parses a <see cref="PersonInfo"/> array from the xml node.
 186    /// </summary>
 187    /// <param name="reader">The <see cref="XmlReader"/>.</param>
 188    /// <param name="personKind">The <see cref="PersonKind"/>.</param>
 189    /// <returns>The <see cref="IEnumerable{PersonInfo}"/>.</returns>
 190    public static IEnumerable<PersonInfo> GetPersonArray(this XmlReader reader, PersonKind personKind)
 4191        => reader.GetStringArray()
 4192            .Select(part => new PersonInfo { Name = part, Type = personKind });
 193}