3

.NET 4.0 中是否有支持 DLR 的 XML 导航和阅读类?例如,假设我有这个 XML:

<foo>
   <bar>foobar is here</bar>
   <bar>foobar is also here</bar>
   <baz>foobar is not here</bar>
</foo>

有没有一种简单的方法可以像这样浏览这个 XML:

var doc = SomeDlrEnabledParser.Parse (xmlString);
foreach (var node in doc.foo.bar)
{
    if (node == "foobar is here")
        DoSomething();
    else
        DoSomethingElse();
}

我可以看到上述方法存在问题的很多原因,包括命名空间、属性与元素、区分集合与单个元素、编码的 XML 与文本等。

但是我处理的大部分 XML 都是非常简单和只读的,我愿意接受合理的默认行为,以换取避免“括号和引号汤”,这是在 4.0 之前使用简单 XML 的特点世界。

例如,“点”运算符可以在子元素名称之前检查属性名称。或者非收集操作将自动应用于第一个元素(就像 jQuery 一样)。

.NET 4.0 Framework 类库是否包含类似的内容?如果没有,对一个好的开源项目或支持 DLR 的 XML 库的示例有什么建议吗?

4

1 回答 1

2

我做了一个小测试实现:

public class DynamicXml : DynamicObject, IEnumerable<XNode>
{
    private readonly IEnumerable<XNode> nodes;

    public DynamicXml(params XNode[] nodes)
    {
        this.nodes = nodes;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var children = nodes.OfType<XContainer>().SelectMany(node => node.Elements(binder.Name)).Cast<XNode>().ToArray();
        result = new DynamicXml(children);
        return true;
    }

    public IEnumerator<XNode> GetEnumerator()
    {
        return nodes.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

和例子:

class Program
{
    static void Main(string[] args)
    {
        dynamic dynDoc = new DynamicXml(XDocument.Parse(
            @"<foo>
                <bar>foobar is here</bar>
                <bar>foobar is also here</bar>
                <baz>foobar is not here</baz>
              </foo>"));

        foreach (XElement node in dynDoc.foo.bar)
        {
            if (node.Value == "foobar is here")
                Console.WriteLine("found: {0}", node);
            else
                Console.WriteLine("not found: {0}", node);
        }

        Console.ReadKey(true);
    }
}

但是,似乎这个和其他一些代码之间的接口不是很好。

例如,如果我们想对节点使用 Linq,我们必须首先显式转换为IEnumerable... 否则我们Where将被解释为元素名称。

((DynamicXml)dynXml.foo.bar).Where(x => x.Value == "foobar is here");

您可以Where直接在动态类型上实现,但您必须像这样限定所有 lambda:

foo.bar.Where((Func<XElement,bool>)(x => x.Value == "foobar is here")) 

也就是说,如果您只是从这样的 XML 树中提取值,我认为它可以正常工作。

于 2010-07-28T05:46:43.497 回答