Created
April 12, 2011 12:12
-
-
Save patriksvensson/915398 to your computer and use it in GitHub Desktop.
Uses the dynamic keyword to parse XML.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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