using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
namespace JWH
{
public static class ExtensionXml
{
///
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
///
///
///
/// 하위검색
///
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;
}
}
///
/// 이름으로 노드를 검색하여 첫번째 노드를 반환합니다.
///
///
///
/// 하위검색
///
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;
}
}
///
/// 이름으로 노드를 검색하여 반환합니다.
///
///
///
/// 하위검색
///
public static XmlNode[] GetNodesByName(this XmlDocument sender, string name, bool fullScan = true)
{
List nodes = new List();
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;
}
}
///
/// 이름으로 노드를 검색하여 반환합니다.
///
///
///
/// 하위검색
///
public static XmlNode[] GetNodesByName(this XmlNode sender, string name, bool fullScan = true)
{
List nodes = new List();
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;
}
}
///
/// 경로를 검색하여 반환합니다.
///
///
///
///
public static XmlNode[] GetNodesByPath(this XmlDocument sender, string path)
{
List nodes = new List();
List childs = new List();
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;
}
}
///
/// 경로를 검색하여 반환합니다.
///
///
///
///
public static XmlNode[] GetNodesByPath(this XmlNode sender, string path)
{
List nodes = new List();
List childs = new List();
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;
}
}
///
/// 속성이 동일한 노드를 검색하여 반환한다.
///
///
/// Name의 대/소문자 무시
/// Value의 대/소문자 무시
///
///
private static bool CheckAttributes(this XmlNode sender, bool ignorsCaseName = true, bool ignorsCaseValue = false, params KeyValuePair[] attributes)
{
try
{
foreach (KeyValuePair 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;
}
}
///
/// 노드의 속성을 검색한다
///
///
///
/// Attribute.Name 대/소문자 무시
///
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;
}
///
/// 노드의 속성값을 반환한다
///
///
///
/// Attribute.Name 대/소문자 무시
///
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;
}
///
/// 노드의 속성값을 변경한다
///
///
///
///
/// Attribute.Name 대/소문자 무시
///
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;
}
}
///
/// XmlDocument 내용을 문자열로 반환합니다.
///
///
///
///
///
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;
}
}
///
/// 노드를 XmlDocument에 복사합니다.
///
///
///
///
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;
}
}
///
/// 하위 노드를 생성하고 반환합니다.
///
///
///
///
///
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;
}
}
///
/// 노드를 삭제합니다.
///
///
///
///
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;
}
}
///
/// 노드를 삭제합니다.
///
///
///
///
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;
}
}
///
/// 노드를 삭제합니다.
///
///
///
///
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}";
}
///
/// 문자열에 있는 잘못된 XML 문자를 해당하는 올바른 XML로 바꿉니다.
///
///
/// 잘못된 문자가 있었으나 바뀐 입력 문자열입니다.
public static string XMLEscape(this string sender)
{
try
{
return System.Security.SecurityElement.Escape(sender);
}
catch
{
return sender;
}
}
///
/// 입력 문자열에서 이스케이프된 문자를 변환합니다.
///
///
///
public static string XMLUnescape(this string sender)
{
try
{
return System.Text.RegularExpressions.Regex.Unescape(sender);
}
catch
{
return sender;
}
}
}
}