J2Solutions are the creators of Scribbl ( http://scribbl.net/ ) and Taggl ( http://taggl.net/ ).

Merging collections

JK | Thu, 2008/12/04 - 14:44

tags:

ICollection does not offer a method for merging two collections. As merging collections was exactly what I needed, I wrote a bit of code for it. An extension method seemed to offer the most elegant solution:

public static ICollection<T> Add<T>(this IList<T> self, IList<T> input)
{
	foreach (T item in input)
	{
		self.Add(item);
	}
	return self;
}

Because I've overloaded the Add method, this will now work:

IList<string> list1 = new IList<string>();
IList<string> list2 = new IList<string>();
string name = 'J2';

list1.Add(list2);
list1.Add(name);

For the license to this code, see http://creativecommons.org/licenses/by/3.0/

XmlDocument improved

JK | Fri, 2008/08/29 - 22:10

tags:

On a nice summerday I set out to write a command line tool that would change values in xml documents. You would pass it a document name, an xpath query, and a value, and it would update the element found in the document through the query, and set its content to the new value.

So I created this tool, and all was fine. That is, until I encountered a document that contained namespaces. I created a namespace manager, figured out how to dynamically get the namespace information from the xml document, and now I could use the namespaces in the xpath expression.

Not an impressive feat, but it left me wondering why System.Xml.XmlDocument doesn't do the "heavy" lifting for us. I decided it should, and you'll find my fix after the break.

using System;
namespace J2.Xml
{
	/*		created by http://j2solutions.nl - 20080824
	 *		XmlDocument that automatically loads all namespaces.
	 *		The default namespace, if present, gets the prefix 'default'.
	 *		license:	http://creativecommons.org/licenses/by/3.0/
	 */
	public class XmlDocument : System.Xml.XmlDocument
	{
		private const string DEFAULT_DEFAULT_NS_PREFIX = "default";
		System.Xml.XmlNamespaceManager nsmgr = null;
		public string DefaultNsPrefix { get; set; }
		public XmlDocument()
		{
			DefaultNsPrefix = DEFAULT_DEFAULT_NS_PREFIX;
		}
		#region Load
		public new void Load(string filename)
		{
			base.Load(filename);
			nsmgr = CreateNamespaceMgr(DefaultNsPrefix);
		}
		public new void Load(System.IO.Stream inStream)
		{
			base.Load(inStream);
			nsmgr = CreateNamespaceMgr(DefaultNsPrefix);
		}
		public new void Load(System.IO.TextReader txtReader)
		{
			base.Load(txtReader);
			nsmgr = CreateNamespaceMgr(DefaultNsPrefix);
		}
		public new void Load(System.Xml.XmlReader reader)
		{
			base.Load(reader);
			nsmgr = CreateNamespaceMgr(DefaultNsPrefix);
		}
		#endregion
		#region LoadXml
		public new void LoadXml(string xml)
		{
			base.LoadXml(xml);
			nsmgr = CreateNamespaceMgr(DefaultNsPrefix);
		}
		#endregion
		#region SelectSingleNode
		public new System.Xml.XmlNode SelectSingleNode(string xpath)
		{
			return (null != nsmgr) ? base.SelectSingleNode(xpath, nsmgr) : base.SelectSingleNode(xpath);
		}
		private new System.Xml.XmlNode SelectSingleNode(string xpath, System.Xml.XmlNamespaceManager nsmgr)
		{
			throw new NotSupportedException();
		}
		#endregion
		#region SelectNodes
		public new System.Xml.XmlNodeList SelectNodes(string xpath)
		{
			return (null != nsmgr) ? base.SelectNodes(xpath, nsmgr) : base.SelectNodes(xpath);
		}
		private new System.Xml.XmlNodeList SelectNodes(string xpath, System.Xml.XmlNamespaceManager nsmgr)
		{
			throw new NotSupportedException();
		}
		#endregion
		private System.Xml.XmlNamespaceManager CreateNamespaceMgr(string prefixForDefaultNS)
		{
			System.Collections.Specialized.NameValueCollection namespaces = GetNamespaces(base.DocumentElement, prefixForDefaultNS);
			System.Xml.XmlNamespaceManager namespaceMgr = null;	
			if (0 != namespaces.Count)
			{
				namespaceMgr = new System.Xml.XmlNamespaceManager(base.NameTable);
				for (int i = 0; i < namespaces.Count; i++)
				{
					namespaceMgr.AddNamespace(namespaces.Keys[i], namespaces[i]);
				}
			}
			return namespaceMgr;
		}
		private System.Collections.Specialized.NameValueCollection GetNamespaces(System.Xml.XmlElement doc, string prefixForDefaultNS)
		{
			System.Collections.Specialized.NameValueCollection ret = new System.Collections.Specialized.NameValueCollection();
			foreach (System.Xml.XmlAttribute attr in doc.Attributes)
			{
				if (-1 < attr.Name.IndexOf("xmlns"))
				{
					// xmlns=<uri> is the default namespace, xmlns:<name>=<uri> is a named namespace
					string key = (-1 < attr.Name.IndexOf("xmlns:")) ? attr.Name.Replace("xmlns:", "") : prefixForDefaultNS;
					ret.Add(key, attr.Value);
				}
			}
			return ret;
		}
	}
}

For the license to this code, see http://creativecommons.org/licenses/by/3.0/

Syndicate content