using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml; namespace DataUtils { public class FileResXmlDoc: IDisposable { private string _filepath; private XmlDocument _doc; private bool _available; public FileResXmlDoc (string xmlpath) { Create (xmlpath); } public bool Create (string xmlpath) { Destroy (); if (string.IsNullOrEmpty (xmlpath) || !File.Exists (xmlpath)) { _available = false; return false; } try { _doc = new XmlDocument (); _doc.Load (xmlpath); _filepath = xmlpath; _available = true; } catch { _available = false; } return _available; } public void Destroy () { if (!_available) return; _doc = null; _available = false; _filepath = null; } public void Dispose () { Destroy (); } // Returns the chosen absolute (or resolved) path string or empty if none found public string Get (string id) { if (!_available || _doc == null) return string.Empty; if (string.IsNullOrEmpty (id)) return string.Empty; XmlNode root = _doc.DocumentElement; if (root == null) return string.Empty; foreach (XmlNode node in root.ChildNodes) { var attr = node.Attributes? ["id"]; if (attr == null) continue; if (!string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase)) continue; // Build dpi -> path map var map = new Dictionary (); foreach (XmlNode child in node.ChildNodes) { var dpiAttr = child.Attributes? ["dpi"]; string dpiStr = dpiAttr != null ? dpiAttr.Value : "default"; string text = child.InnerText ?? string.Empty; int dpiKey = 0; if (string.Equals (dpiStr, "default", StringComparison.OrdinalIgnoreCase)) { dpiKey = 0; } else { int parsed; if (int.TryParse (dpiStr, out parsed)) dpiKey = parsed; else dpiKey = 0; } // Resolve relative path relative to xml file directory string candidate = text; if (!Path.IsPathRooted (candidate) && !string.IsNullOrEmpty (_filepath)) { string dir = Path.GetDirectoryName (_filepath); if (!string.IsNullOrEmpty (dir)) candidate = Path.Combine (dir, candidate); } // Normalize try { candidate = Path.GetFullPath (candidate); } catch { /* ignore */ } // Insert/overwrite by key (keep last if duplicate) map [dpiKey] = candidate; } // Convert map to list and sort by string value (to mimic original) var list = map.Select (kv => new KeyValuePair (kv.Key, kv.Value)).ToList (); list.Sort ((a, b) => string.CompareOrdinal (a.Value, b.Value)); // Keep only those whose file exists var existList = new List> (); foreach (var kv in list) { if (!string.IsNullOrEmpty (kv.Value) && File.Exists (kv.Value)) existList.Add (kv); } int dpiPercent = UITheme.GetDPI (); // uses earlier helper // Find first with dpi >= dpiPercent foreach (var kv in existList) { if (kv.Key >= dpiPercent) return kv.Value; } // otherwise return first existing candidate if (existList.Count > 0) return existList [0].Value; return string.Empty; } return string.Empty; } // Overloads for convenience //public string Get (System.String idAsString) { return Get (idAsString); } } public class StringResXmlDoc: IDisposable { private XmlDocument doc; private bool isValid; public bool IsValid { get { return isValid; } } public StringResXmlDoc () { } public StringResXmlDoc (string filePath) { Create (filePath); } public bool Create (string filePath) { Destroy (); if (string.IsNullOrEmpty (filePath) || !File.Exists (filePath)) return false; try { doc = new XmlDocument (); doc.Load (filePath); isValid = true; return true; } catch { Destroy (); return false; } } public void Destroy () { doc = null; isValid = false; } public void Dispose () { Destroy (); GC.SuppressFinalize (this); } public string Get (string id) { if (!isValid || doc == null || string.IsNullOrEmpty (id)) return string.Empty; XmlElement root = doc.DocumentElement; if (root == null) return string.Empty; foreach (XmlNode node in root.ChildNodes) { if (node.Attributes == null) continue; XmlAttribute idAttr = node.Attributes ["id"]; if (idAttr == null) continue; if (!StringEqualsNormalized (idAttr.Value, id)) continue; Dictionary langValues = new Dictionary (StringComparer.OrdinalIgnoreCase); foreach (XmlNode sub in node.ChildNodes) { if (sub.Attributes == null) continue; XmlAttribute langAttr = sub.Attributes ["name"]; if (langAttr == null) continue; string lang = langAttr.Value; if (!string.IsNullOrEmpty (lang)) { langValues [lang] = sub.InnerText; } } return GetSuitableLanguageValue (langValues); } return string.Empty; } public string GetString (string id) => Get (id); public string this [string id] { get { return Get (id); } } private static bool StringEqualsNormalized (string a, string b) { return string.Equals ( a != null ? a.Trim () : null, b != null ? b.Trim () : null, StringComparison.OrdinalIgnoreCase ); } private static string GetSuitableLanguageValue ( Dictionary values) { if (values == null || values.Count == 0) return string.Empty; CultureInfo culture = CultureInfo.CurrentUICulture; string val; if (values.TryGetValue (culture.Name, out val)) return val; if (values.TryGetValue (culture.TwoLetterISOLanguageName, out val)) return val; if (values.TryGetValue ("en", out val)) return val; foreach (string v in values.Values) return v; return string.Empty; } } }