1

さまざまな XML スキームが作成されるクラスがあります。オプションの要素と属性の条件演算子を使用して、1 つの (非常に長い) ステートメントでさまざまな動的 XDocuments を作成します。

XDocuments をクラスに変換する必要がありますが、それらは異なるスキームからのものであるため、多くの要素とサブ要素はオプションである可能性があります。これを行う唯一の方法は、多くの if ステートメントを使用することです。

このアプローチはあまり LINQ とは思えず、XDocument を作成するときよりもはるかに多くのコードを使用するため、これを行うためのより良い方法があるかどうか疑問に思いました。

例は、取得することです

<?xml version="1.0"?>
<root xmlns="somenamespace">
    <object attribute1="This is Optional" attribute2="This is required">
        <element1>Required</element1>
        <element1>Optional</element1>
        <List1>
            Optional List Of Elements
        </List1>
        <List2>
            Required List Of Elements
        </List2>
    </object>
</root>

の中へ

public class Object()
{
    public string Attribute1;
    public string Attribute2;
    public string Element1;
    public string Element2;
    public List<ListItem1> List1;
    public List<ListItem2> List2;
}

これよりも LINQ に適した方法で:

public bool ParseXDocument(string xml)
{
    XNamespace xn = "somenamespace";            
    XDocument document = XDocument.Parse(xml);

    XElement elementRoot = description.Element(xn + "root");
    if (elementRoot != null)
    {
        //Get Object Element
        XElement elementObject = elementRoot.Element(xn + "object");
        if(elementObject != null)
        {
            if(elementObject.Attribute(xn + "attribute1") != null)
            {
                Attribute1 = elementObject.Attribute(xn + "attribute1");
            }
            if(elementObject.Attribute(xn + "attribute2") != null)
            {
                Attribute2 = elementObject.Attribute(xn + "attribute2");
            }
            else
            {
                //This is a required Attribute so return false
                return false;
            }
            //If, If/Elses get deeper and deeper for the next elements and lists etc.... 
        }
        else
        {
            //Object is a required element so return false
            return false;
        }
    }
    else
    {
        //Root is a required element so return false
        return false;
    }
    return true;
}

更新: ParseXDocument メソッドが「オブジェクト」クラス内にあることを明確にするためです。xml ドキュメントを受信するたびに、Object クラス インスタンスの値の一部またはすべてが更新されます。

4

2 に答える 2

2

コード:

private static readonly XNamespace xn = "somenamespace";

public bool ParseXDocument(string xml)
{
    XDocument document = XDocument.Parse(xml);

    var obj = document.Root.Element(xn + "object");
    if (obj == null)
        return false;

    Attribute1 = (string)obj.Attribute("attribute1");
    Attribute2 = (string)obj.Attribute("attribute2");
    Element1 = (string)obj.Element(xn + "element1");
    Element2 = (string)obj.Elements(xn + "element1").ElementAtOrDefault(1);
    // ...

    return Validate();
}
于 2012-11-16T04:27:08.793 に答える
0

以下に、必要な可読性を実現するのに役立つ拡張メソッドをいくつか示します。現在の形式のコードは、必要な要素がすべて見つかったかどうかに応じて true/false を返すことをサポートしていません。その点で dtb のアドバイスを採用することをお勧めします。詳細を解析してから検証を実行してください。

XML 構造の反復を繰り返すなどの欠点もありますが、問題が発生した場合は、少しの想像力でそれを克服できると確信しています。

MyObject は次のようになります。 public class MyObject { public string Attribute1; 公開文字列 Attribute2; パブリック文字列 Element1; パブリック文字列 Element2; 公開リスト List1; 公開リスト List2;

    public void ParseXDocument(string xml)
    {
        XNamespace xn = "somenamespace";            
        XDocument document = XDocument.Parse(xml);

        XElement elementRoot = document.Root;
        elementRoot.MatchElement(xn.GetName("object"), xObject => {
            xObject.MatchAttribute("attribute1", (x,a) => this.Attribute1 = (string)a);
            xObject.MatchAttribute("attribute2", (x,a) => this.Attribute2 = (string)a);
            xObject.MatchElement(xn.GetName("element1"), x => this.Element1 = (string)x);
            xObject.MatchElement(xn.GetName("element2"), x => this.Element2 = (string)x);
        });
    }
}

これをサポートする拡張メソッドは次のとおりです。 public static class XElementExtensions {

    public static XElement MatchAttribute(this XElement x, XName name, Action<XElement, XAttribute> action) {
        foreach (var a in x.Attributes(name)) {
            action(x, a);
        }

        return x;
    }

    public static XElement MatchElement(this XElement x, XName name, Action<XElement> action) {
        foreach (var child in x.Elements(name)) {
            action(child);
        }

        return x;
    }
}

最後に、LinqPad でテストするために使用したサンプル ドライバー コードを次に示します。

void Main()
{
    var xml = @"<?xml version=""1.0""?>
<root xmlns=""somenamespace"">
    <object attribute1=""This is Optional"" attribute2=""This is required"">
        <element1>Required</element1>
        <element2>Optional</element2>
        <List1>
            Optional List Of Elements
        </List1>
        <List2>
            Required List Of Elements
        </List2>
    </object>
</root> 
    ";

    var o = new MyObject();

    o.ParseXDocument(xml);
    o.Dump();
}
于 2012-11-16T06:01:30.993 に答える