Skip to content

Instantly share code, notes, and snippets.

@patriksvensson
Created April 12, 2011 12:12
Show Gist options
  • Save patriksvensson/915398 to your computer and use it in GitHub Desktop.
Save patriksvensson/915398 to your computer and use it in GitHub Desktop.
Uses the dynamic keyword to parse XML.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using System.Xml;
using System.Xml.Linq;
using System.Collections;
namespace Patrik.Gists
{
/////////////////////////////////////////////////////////////////
// XML:
//
// <User IsActive="False">
// <Name HasLastName="True">Patrik Svensson</Name>
// </User>
//
// C#:
//
// dynamic parser = new DynamicXmlReader(document);
// Assert.Equals("False", parser.User.IsActive);
// Assert.Equals("Patrik Svensson", parser.User.Name);
// Assert.Equals("True", parser.User.Name.HasLastName);
/////////////////////////////////////////////////////////////////
public class DynamicXmlReader : DynamicObject
{
XmlElement _root;
public DynamicXmlReader(XmlDocument document)
{
_root = document.DocumentElement;
}
public DynamicXmlReader(XmlElement root)
{
_root = root;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
return false;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
#region Sanity Check
if (_root == null)
{
result = null;
return false;
}
#endregion
// Want to know the number of child nodes?
if (binder.Name == "Count")
{
result = _root.ChildNodes != null ? _root.ChildNodes.Count : 0;
return true;
}
// Is this an attribute?
XmlAttribute attribute = _root.Attributes.GetNamedItem(binder.Name) as XmlAttribute;
if (attribute != null)
{
result = attribute.Value;
return true;
}
else
{
// Is this an element?
XmlElement element = (XmlElement)_root.SelectSingleNode(binder.Name);
if (element != null)
{
// Reached a leaf?
if (element.ChildNodes.Count == 1 && element.ChildNodes[0].NodeType == XmlNodeType.Text)
{
// Take the value of the leaf.
result = element.ChildNodes[0].Value;
}
else
{
// Wrap the element in a dynamic object.
result = new DynamicXmlReader(element);
}
return true;
}
else
{
// Got an owner document with an element?
if (_root.OwnerDocument != null && _root.OwnerDocument.DocumentElement != null)
{
// Same name as the binder name?
if (_root.OwnerDocument.DocumentElement.Name == binder.Name)
{
// We've accessed the root.
result = new DynamicXmlReader(_root.OwnerDocument.DocumentElement);
return true;
}
}
result = null;
return false;
}
}
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
result = new DynamicXmlReader((XmlElement)_root.ChildNodes[(int)indexes[0]]);
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment