/*
var xml = @"<root><books>
<book is_read=""false""><author>Test</author></book>
<book is_read=""true""><author>Test2</author></book>
</books></root>";

dynamic book = new DynamicXml(xml);

Console.WriteLine(book.Book[1]);
*/
public class DynamicXml : DynamicObject, IEnumerable
{
static readonly DynamicXml Null = new DynamicXml();

#region Friendly Xml

static readonly Regex TagRegex = new Regex(@"<(/?)(.*?)>");
static readonly Regex AttrRegex = new Regex(@"(\w+)=""");

static string Friendly(string txt)
{
var dictionary = new Dictionary<string, string>();
Func<string, string> formatTag = tag =>
{
if (!dictionary.ContainsKey(tag))
dictionary.Add(tag, FormatText(tag));
return dictionary[tag];
};

var result = TagRegex.Replace(txt, delegate(Match match)
{
var original = match.Result("$2");
string worked;

#region tag work

if (original.Contains(" "))
{
var index = original.IndexOf(" ", StringComparison.Ordinal);
worked = formatTag(original.Substring(0, index)) +
AttrRegex.Replace(original.Substring(index),
attr => formatTag(attr.Result("$1")) + "=\"");
}
else
{
worked = formatTag(original);
}

#endregion

return match.Result("<$1") + worked + ">";

});

return result;
}

static string FormatText(string txt)
{
var sb = new StringBuilder();
var up = true;

foreach (var c in txt)
{
if (c == '_')
{
up = true;
}
else
{
if (up)
{
sb.Append(c.ToString(CultureInfo.InvariantCulture).ToUpper());
up = false;
}
else
{
sb.Append(c.ToString(CultureInfo.InvariantCulture).ToLower());
}
}
}

return sb.ToString();
}

#endregion

private readonly List<XElement> _elements = new List<XElement>();

DynamicXml() { }

public DynamicXml(string text, bool friendly = true)
{
try
{
var doc = XDocument.Parse(text);

if (friendly)
{
var formatted = doc.ToString();
doc = XDocument.Parse(Friendly(formatted));
}

_elements = new List<XElement> { doc.Root };
}
catch (Exception ex)
{
Console.Write(ex);
throw;
}
}

protected DynamicXml(XElement element)
{
_elements = new List<XElement> { element };
}

protected DynamicXml(IEnumerable<XElement> elements)
{
_elements = new List<XElement>(elements);
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = Null;

switch (binder.Name)
{
case "Count":
result = _elements.Count;
break;
default:
{
var items = _elements.Descendants(XName.Get(binder.Name)).ToList();

if (!items.Any())
{
if (_elements.Count == 1)
{
var attr = _elements[0].Attribute(XName.Get(binder.Name));

if (null != attr)
{
result = attr.Value;
}
}
}
else
{
result = new DynamicXml(items);
}
}
break;
}

return true;
}

public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
{
var index = (int)indexes[0];

result = new DynamicXml(_elements[index]);

return true;
}

public IEnumerator GetEnumerator()
{
return _elements.Select(element => new DynamicXml(element)).GetEnumerator();
}

public override string ToString()
{
if (_elements.Count == 1 && !_elements[0].HasElements)
{
return _elements[0].Value;
}

return string.Join("\n", _elements);
}

public static implicit operator string(DynamicXml dyn)
{
return Null == dyn ? null : dyn.ToString();
}

public static implicit operator DynamicXml(string xml)
{
return new DynamicXml(xml);
}
}

DynamicXml的更多相关文章

  1. 记录下DynamicXml和HtmlDocument 使用方式

    之前解析都是XmlDocument.Load 而现在可以利用DynamicXml生成Dynamic对象实现强类型操作,很好用. /// <summary> /// 根据Xml路径动态解析成 ...

  2. 理解C# 4 dynamic(3) – DynamicObject的使用

    上篇文章"理解C# 4 dynamic(2) – ExpandoObject的使用" 了解了ExpandoObject的基本使用. 但ExpandoObject的问题就是它是一个万 ...

  3. 超级懒汉编写的基于.NET的微信SDK

    一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的xml消息在组装成实体类,所以会比较臃肿,现 ...

  4. [转贴]超级懒汉编写的基于.NET的微信SDK

    一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的xml消息在组装成实体类,所以会比较臃肿,现 ...

  5. 十七、C# 反射、特性和动态编程

    反射.特性和动态编程   1.访问元数据 2.成员调用 3.泛型上的反射 4.自定义特性 5.特性构造器 6.具名参数 7.预定义特性 8.动态编程   特性(attribute)是在一个程序集中插入 ...

  6. 基于.NET的微信SDK

    超级懒汉编写的基于.NET的微信SDK   一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的 ...

  7. 【第二十篇】C#微信H5支付 非微信内浏览器H5支付 浏览器微信支付

    微信开发者文档 微信H5支付官方文档   请阅读清楚  最起码把所有参数看一遍 这个地方也可以看看 微信案例 http://wxpay.wxutil.com/mch/pay/h5.v2.php,请在微 ...

  8. C# - 表达式与语句

    表达式与语句(Expression&Statement) 操作数(Operands) 1.数字.2.字符.3.变量.4.类型.5.对象.6.方法 操作符(Operator) 参考:C# - 操 ...

  9. C#学习笔记12

    1.在使用反射时,反射可以绕过安全访问级别(private.protected)修饰的类或属性,来获取需要的信息. 2.泛型的反射:可以使用Type.ContainsGenericParameters ...

随机推荐

  1. Kotlin基本语法和使用

    Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发.与Java相比,Kotlin的语法更简洁.更具表达性,而且提供了更多的特性. Kotlin是使用Java开发者的思维被创 ...

  2. 2017全球互联网技术大会回顾(附PPT)

    有幸遇见 GITC2017上海站,刚好遇见你! 为期两天(6.23~24)的GITC大会在上海举行,我有幸参加了24号的那场,也就是上周六,之所以今天才来回顾,是我想等PPT出来后分享给大家! 这应该 ...

  3. [leetcode-583-Delete Operation for Two Strings]

    Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 t ...

  4. 【LeetCode】289. Game of Life

    题目: According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a ce ...

  5. 把对象列表转化成json数据格式

    package JsonTest; import java.util.ArrayList; import java.util.List; public class test { public stat ...

  6. vue和mvvm的一些小区别

    Vue.js 和 MVVM 小细节   MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这 ...

  7. voa 2015.4.29

    Nepal has declared three days of mourning for the victims of Saturday's 7.8 magnitude earthquake tha ...

  8. 《javascript 高级程序设计》笔记

    1-4章 1.变量①.ECMAScript 变量是松散类型的,也就是说可以用来保存任何类型的数据.换句话说每个变量仅仅是一个用于保存值的占位符.②.如果在函数中使用var定义一个变量,那么这个变量在函 ...

  9. 用 volume container 共享数据 - 每天5分钟玩转 Docker 容器技术(42)

    volume container 是专门为其他容器提供 volume 的容器.它提供的卷可以是 bind mount,也可以是 docker managed volume.下面我们创建一个 volum ...

  10. 【Vue】详解Vue组件系统

    Vue渲染的两大基础方式 new 一个Vue的实例 这个我们一般会使用在挂载根节点这一初始化操作上: new Vue({ el: '#app' }) 注册组件并使用—— 全局注册 通过Vue.comp ...