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、すべてのラムダを次のように修飾する必要があります。

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

とはいえ、このように XML ツリーから値を抽出するだけであれば、問題なく動作すると思います。

于 2010-07-28T05:46:43.497 に答える