使用 C# 4.0 动态 XML 导航和阅读?

发布于 2024-09-11 07:59:42 字数 757 浏览 12 评论 0原文

.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 都非常简单且只读,我愿意接受合理的默认行为,以换取避免“括号和引号汤”的工作 在 4.0 之前的世界中使用简单的 XML。

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

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

Is there a DLR-enabled XML navigation and reading class available in .NET 4.0? For example, imagine I have this XML:

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

Is there an easy way to navigate through this XML like this:

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

I can see lots of reasons why the approach above would be problematic, including namespaces, attributes vs. elements, differentiating collections vs. single elements, encoded XML vs text, etc.

But much of the XML I deal with is very simple and read-only, and I'd be willing to accept sensible default behaviors in exchange for avoiding the "parentheses and quote soup" that's characteristic of working with simple XML in a pre-4.0 world.

For example, the "dot" operator could check attribute names before subelement names. Or non-collection operations would be automatically applied to the first element (like jQuery does).

Does the .NET 4.0 Framework Class Library contain anything like this? if not, any recommendations for a good open-source project or sample of a DLR-enabled XML library?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十年九夏 2024-09-18 07:59:42

我做了一些测试实现:

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 树中提取值,我认为它可以正常工作。

I did a little test implementation:

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();
    }
}

And example:

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);
    }
}

However, it seems that the interface between this and some other code is not so nice.

For example, if we wanted to use Linq against the nodes we must first explicitly cast to an IEnumerable... otherwise our Where will be interpreted as an element name.

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

You can implement Where directly on the dynamic type, but you must then qualify all lambdas like this:

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

That said, if you're just extracting values from an XML tree like this, I think it works okay.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文