forked from pgstath/Sharp.Xmpp
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathXml.cs
More file actions
135 lines (127 loc) · 5.66 KB
/
Xml.cs
File metadata and controls
135 lines (127 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
namespace XMPPEngineer
{
/// <summary>
/// Provides a factory method for creating XmlElement instances and adds
/// a couple of useful shortcut extensions to the XmlElement class.
/// </summary>
internal static class Xml
{
/// <summary>
/// Creates a new XmlElement instance.
/// </summary>
/// <param name="name">The name of the element.</param>
/// <param name="namespace">The namespace of the element.</param>
/// <returns>An initialized instance of the XmlElement class.</returns>
/// <exception cref="ArgumentNullException">The name parameter is null.</exception>
/// <exception cref="ArgumentException">The name parameter is the
/// empty string.</exception>
/// <exception cref="XmlException">The name or the namespace parameter
/// is invalid.</exception>
public static XmlElement Element(string name, string @namespace = null)
{
name.ThrowIfNullOrEmpty("name");
return new XmlDocument().CreateElement(name, @namespace);
}
/// <summary>
/// Adds the specified element to the end of the list of child nodes, of
/// this node.
/// </summary>
/// <param name="e">The XmlElement instance the method is invoked for.</param>
/// <param name="child">The node to add.</param>
/// <returns>A reference to the XmlElement instance.</returns>
public static XmlElement Child(this XmlElement e, XmlElement child)
{
XmlNode imported = e.OwnerDocument.ImportNode(child, true);
e.AppendChild(imported);
return e;
}
/// <summary>
/// Sets the value of the attribute with the specified name.
/// </summary>
/// <param name="e">The XmlElement instance the method is invoked for.</param>
/// <param name="name">The name of the attribute to create or alter.</param>
/// <param name="value">The value to set for the attribute.</param>
/// <returns>A reference to the XmlElement instance.</returns>
public static XmlElement Attr(this XmlElement e, string name, string value)
{
e.SetAttribute(name, value);
return e;
}
/// <summary>
/// Adds the specified text to the end of the list of child nodes, of
/// this node.
/// </summary>
/// <param name="e">The XmlElement instance the method is invoked for.</param>
/// <param name="text">The text to add.</param>
/// <returns>A reference to the XmlElement instance.</returns>
public static XmlElement Text(this XmlElement e, string text)
{
e.AppendChild(e.OwnerDocument.CreateTextNode(text));
return e;
}
/// <summary>
/// Serializes the XmlElement instance into a string.
/// </summary>
/// <param name="e">The XmlElement instance the method is invoked for.</param>
/// <param name="xmlDeclaration">true to include a XML declaration,
/// otherwise false.</param>
/// <param name="leaveOpen">true to leave the tag of an empty element
/// open, otherwise false.</param>
/// <returns>A textual representation of the XmlElement instance.</returns>
public static string ToXmlString(this XmlElement e, bool xmlDeclaration = false,
bool leaveOpen = false)
{
// avoid duplicate namespaces on elements by storing each in the list
System.Collections.Generic.IList<string> ns = new System.Collections.Generic.List<string>();
// Can't use e.OuterXml because it "messes up" namespaces for elements with
// a prefix, i.e. stream:stream (What it does is probably correct, but just
// not what we need for XMPP).
StringBuilder b = new StringBuilder("<" + e.Name);
if (!String.IsNullOrEmpty(e.NamespaceURI))
b.Append(" xmlns='" + e.NamespaceURI + "'");
foreach (XmlAttribute a in e.Attributes)
{
// 21 April 2017 - Removed skipping the namespaces so we can add custom namespaces.
//if (a.Name == "xmlns")
// continue;
if (a.Name == "xmlns")
{
// If the namespace above was added to it, we don't want to add a duplicate. Causes of building Xml through strings.
if (!String.IsNullOrEmpty(e.NamespaceURI)) continue;
if (ns.Contains(a.Value))
continue;
else
ns.Add(a.Value);
}
if (a.Value != null)
b.Append(" " + a.Name + "='" + SecurityElement.Escape(a.Value.ToString())
+ "'");
}
if (e.IsEmpty)
b.Append("/>");
else
{
b.Append(">");
foreach (var child in e.ChildNodes)
{
if (child is XmlElement)
b.Append(((XmlElement)child).ToXmlString());
else if (child is XmlText)
b.Append(((XmlText)child).InnerText);
}
b.Append("</" + e.Name + ">");
}
string xml = b.ToString();
if (xmlDeclaration)
xml = "<?xml version='1.0' encoding='UTF-8'?>" + xml;
if (leaveOpen)
return Regex.Replace(xml, "/>$", ">");
return xml;
}
}
}