604 lines
20 KiB
C#
604 lines
20 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Xml;
|
|
|
|
namespace JWH
|
|
{
|
|
|
|
public static class ExtensionXml
|
|
{
|
|
|
|
/// <summary>
|
|
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="fullScan">하위검색</param>
|
|
/// <returns></returns>
|
|
public static XmlNode GetSingleNodeByName(this XmlDocument sender, string name, bool fullScan = true)
|
|
{
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, name, true) == 0) return node;
|
|
}
|
|
if (fullScan == false) return null;
|
|
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
XmlNode result = node.GetSingleNodeByName(name);
|
|
if (result != null) return result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="fullScan">하위검색</param>
|
|
/// <returns></returns>
|
|
public static XmlNode GetSingleNodeByName(this XmlNode sender, string name, bool fullScan = true)
|
|
{
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, name, true) == 0) return node;
|
|
}
|
|
if (fullScan == false) return null;
|
|
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
XmlNode result = node.GetSingleNodeByName(name);
|
|
if (result != null) return result;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이름으로 노드를 검색하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="fullScan">하위검색</param>
|
|
/// <returns></returns>
|
|
public static XmlNode[] GetNodesByName(this XmlDocument sender, string name, bool fullScan = true)
|
|
{
|
|
List<XmlNode> nodes = new List<XmlNode>();
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, name, true) == 0)
|
|
nodes.Add(node);
|
|
}
|
|
if (fullScan == false) return nodes.ToArray();
|
|
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
nodes.AddRange(node.GetNodesByName(name));
|
|
}
|
|
|
|
return nodes.ToArray();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이름으로 노드를 검색하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="fullScan">하위검색</param>
|
|
/// <returns></returns>
|
|
public static XmlNode[] GetNodesByName(this XmlNode sender, string name, bool fullScan = true)
|
|
{
|
|
List<XmlNode> nodes = new List<XmlNode>();
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, name, true) == 0)
|
|
nodes.Add(node);
|
|
}
|
|
if (fullScan == false) return nodes.ToArray();
|
|
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
nodes.AddRange(node.GetNodesByName(name));
|
|
}
|
|
|
|
return nodes.ToArray();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 경로를 검색하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="path"></param>
|
|
/// <returns></returns>
|
|
public static XmlNode[] GetNodesByPath(this XmlDocument sender, string path)
|
|
{
|
|
List<XmlNode> nodes = new List<XmlNode>();
|
|
List<XmlNode> childs = new List<XmlNode>();
|
|
try
|
|
{
|
|
string[] names = path.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, names[0], true) == 0)
|
|
{
|
|
if (names.Length > 1) childs.Add(node);
|
|
else nodes.Add(node);
|
|
}
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 1; i < names.Length; i++)
|
|
sb.AppendFormat($"/{names[i]}");
|
|
|
|
foreach (XmlNode node in childs)
|
|
{
|
|
nodes.AddRange(node.GetNodesByPath(sb.ToString()));
|
|
}
|
|
|
|
return nodes.ToArray();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 경로를 검색하여 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="path"></param>
|
|
/// <returns></returns>
|
|
public static XmlNode[] GetNodesByPath(this XmlNode sender, string path)
|
|
{
|
|
List<XmlNode> nodes = new List<XmlNode>();
|
|
List<XmlNode> childs = new List<XmlNode>();
|
|
try
|
|
{
|
|
string[] names = path.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (string.Compare(node.Name, names[0], true) == 0)
|
|
{
|
|
if (names.Length > 1) childs.Add(node);
|
|
else nodes.Add(node);
|
|
}
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 1; i < names.Length; i++)
|
|
sb.AppendFormat($"/{names[i]}");
|
|
|
|
foreach (XmlNode node in childs)
|
|
{
|
|
nodes.AddRange(node.GetNodesByPath(sb.ToString()));
|
|
}
|
|
|
|
return nodes.ToArray();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 속성이 동일한 노드를 검색하여 반환한다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="ignorsCaseName">Name의 대/소문자 무시</param>
|
|
/// <param name="ignorsCaseValue">Value의 대/소문자 무시</param>
|
|
/// <param name="attributes"></param>
|
|
/// <returns></returns>
|
|
private static bool CheckAttributes(this XmlNode sender, bool ignorsCaseName = true, bool ignorsCaseValue = false, params KeyValuePair<string, string>[] attributes)
|
|
{
|
|
try
|
|
{
|
|
foreach (KeyValuePair<string, string> pair in attributes)
|
|
{
|
|
foreach (XmlAttribute attribute in sender.Attributes)
|
|
{
|
|
if (string.Compare(pair.Key, attribute.Name, ignorsCaseName) == 0)
|
|
if (string.Compare(pair.Value, attribute.Value, ignorsCaseValue) == 0) continue;
|
|
else return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드의 속성을 검색한다
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
|
/// <returns></returns>
|
|
public static XmlAttribute GetAttribute(this XmlNode sender, string name, bool ignorsCase = true)
|
|
{
|
|
if (sender == null || sender.Attributes == null) return null;
|
|
|
|
foreach (XmlAttribute attribute in sender.Attributes)
|
|
{
|
|
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
|
return attribute;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드의 속성값을 반환한다
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
|
/// <returns></returns>
|
|
public static string GetAttributeValue(this XmlNode sender, string name, bool ignorsCase = true)
|
|
{
|
|
if (sender == null) return null;
|
|
foreach (XmlAttribute attribute in sender.Attributes)
|
|
{
|
|
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
|
return attribute.Value;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드의 속성값을 변경한다
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="value"></param>
|
|
/// <param name="ignorsCaseName">Attribute.Name 대/소문자 무시</param>
|
|
/// <returns></returns>
|
|
public static string SetAttributeValue(this XmlNode sender, string name, string value, bool ignorsCase = true)
|
|
{
|
|
foreach (XmlAttribute attribute in sender.Attributes)
|
|
{
|
|
if (string.Compare(attribute.Name, name, ignorsCase) == 0)
|
|
{
|
|
attribute.Value = value;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static void PropertiesCopyAttribute(this XmlNode sender, object dest)
|
|
{
|
|
try
|
|
{
|
|
foreach (XmlAttribute attribute in sender.Attributes)
|
|
dest.PropertySet(attribute.Name, attribute.Value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
}
|
|
}
|
|
|
|
public static void PropertiesCopy(this XmlNode sender, object dest)
|
|
{
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
dest.PropertySet(node.Name, node.InnerText);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
XLogger.Instance.Fatal(ex);
|
|
}
|
|
}
|
|
|
|
public static string GetText(this XmlNode sender)
|
|
{
|
|
if (sender.ChildNodes.Count <= 0) return string.Empty;
|
|
|
|
string rtnValue = null;
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (node.GetType() == typeof(XmlText))
|
|
rtnValue = node.InnerText;
|
|
}
|
|
|
|
return rtnValue;
|
|
}
|
|
|
|
public static void SetText(this XmlNode sender, string value)
|
|
{
|
|
XmlNode nodeText = null;
|
|
foreach (XmlNode node in sender.ChildNodes)
|
|
{
|
|
if (node.GetType() == typeof(XmlText))
|
|
{
|
|
nodeText.InnerText = value;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (sender.ChildNodes.Count == 0)
|
|
{
|
|
sender.InnerText = value;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// XmlDocument 내용을 문자열로 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="indent"></param>
|
|
/// <param name="haeder"></param>
|
|
/// <returns></returns>
|
|
public static string GetBeautify(this XmlDocument sender, int indent = 2, bool haeder = true)
|
|
{
|
|
try
|
|
{
|
|
string rtn = string.Empty;
|
|
|
|
using (MemoryStream stream = new MemoryStream())
|
|
{
|
|
XmlWriterSettings settings = new XmlWriterSettings
|
|
{
|
|
Encoding = new UTF8Encoding(false),
|
|
Indent = true,
|
|
IndentChars = "".PadLeft(indent),
|
|
NewLineChars = Environment.NewLine,
|
|
NewLineHandling = NewLineHandling.Replace,
|
|
};
|
|
|
|
using (XmlWriter writer = XmlWriter.Create(stream, settings))
|
|
sender.Save(writer);
|
|
|
|
rtn = Encoding.UTF8.GetString(stream.ToArray());
|
|
}
|
|
|
|
if (haeder == false)
|
|
{
|
|
int index = rtn.IndexOf("<?");
|
|
if (index >= 0)
|
|
{
|
|
index = rtn.IndexOf("<", index + 1);
|
|
rtn = rtn.Substring(index);
|
|
}
|
|
}
|
|
|
|
return rtn;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드를 XmlDocument에 복사합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="document"></param>
|
|
/// <param name="isChild"></param>
|
|
public static void CopyValue(this XmlNode sender, XmlDocument document, bool isChild = true)
|
|
{
|
|
try
|
|
{
|
|
string path = sender.GetFullPath();
|
|
foreach (XmlNode child in sender.ChildNodes)
|
|
{
|
|
if (child.NodeType == XmlNodeType.Text)
|
|
{
|
|
XmlNode dest = document.SelectSingleNode(path);
|
|
if (dest == null) continue;
|
|
|
|
if (dest.ChildNodes.Count == 0)
|
|
{
|
|
XmlNode valueNode = document.CreateNode("text", "", "");
|
|
dest.AppendChild(valueNode);
|
|
}
|
|
foreach (XmlNode destChild in dest.ChildNodes)
|
|
if (destChild.NodeType == XmlNodeType.Text) destChild.Value = child.Value;
|
|
}
|
|
else
|
|
{
|
|
if (isChild) child.CopyValue(document);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 하위 노드를 생성하고 반환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="innerText"></param>
|
|
/// <returns></returns>
|
|
public static XmlNode CreateChildNode(this XmlNode sender, string name, string innerText = "", int index = -1, bool isAfter = true)
|
|
{
|
|
try
|
|
{
|
|
XmlDocument document = sender.OwnerDocument;
|
|
XmlNode childNode = document.CreateElement(name);
|
|
if (!string.IsNullOrEmpty(innerText)) childNode.InnerText = innerText;
|
|
|
|
if (index < 0 || index > sender.ChildNodes.Count)
|
|
{
|
|
sender.AppendChild(childNode);
|
|
return childNode;
|
|
}
|
|
|
|
XmlNode refNode = sender.ChildNodes[index];
|
|
if (isAfter) sender.InsertAfter(childNode, refNode);
|
|
else sender.InsertBefore(childNode, refNode);
|
|
|
|
return childNode;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드를 삭제합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="index"></param>
|
|
/// <returns></returns>
|
|
public static bool RemoveChildNode(this XmlNode sender, int index)
|
|
{
|
|
try
|
|
{
|
|
if (index >= sender.ChildNodes.Count) return false;
|
|
XmlNode node = sender.ChildNodes[index];
|
|
if (node != null) sender.RemoveChild(node);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드를 삭제합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
public static bool RemoveChildNode(this XmlNode sender, string name)
|
|
{
|
|
try
|
|
{
|
|
XmlNode node = sender.GetSingleNodeByName(name);
|
|
if (node == null) return false;
|
|
sender.RemoveChild(node);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 노드를 삭제합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
public static bool RemoveChildNodes(this XmlNode sender, string name)
|
|
{
|
|
try
|
|
{
|
|
foreach (XmlNode node in sender.GetNodesByName(name))
|
|
sender.RemoveChild(node);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
private static string GetFullPath(this XmlNode sender)
|
|
{
|
|
if (sender == null) return string.Empty;
|
|
if (sender.ParentNode == null || sender.ParentNode.NodeType != XmlNodeType.Element)
|
|
return $"//{sender.Name}";
|
|
|
|
return $"{sender.ParentNode.GetFullPath()}/{sender.Name}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 문자열에 있는 잘못된 XML 문자를 해당하는 올바른 XML로 바꿉니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <returns>잘못된 문자가 있었으나 바뀐 입력 문자열입니다.</returns>
|
|
public static string XMLEscape(this string sender)
|
|
{
|
|
try
|
|
{
|
|
return System.Security.SecurityElement.Escape(sender);
|
|
}
|
|
catch
|
|
{
|
|
return sender;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 입력 문자열에서 이스케이프된 문자를 변환합니다.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <returns></returns>
|
|
public static string XMLUnescape(this string sender)
|
|
{
|
|
try
|
|
{
|
|
return System.Text.RegularExpressions.Regex.Unescape(sender);
|
|
}
|
|
catch
|
|
{
|
|
return sender;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|