Инициализация членов XML для XmlSerializer с использованием C # - PullRequest
0 голосов
/ 08 сентября 2018

У меня ниже XML, и мне нужно десериализовать, чтобы получить значение «ThreadGroup.num_threads», «ThreadGroup.ramp_time», «HTTPSampler.path» и «HTTPSampler.domain».

    <TestPlan>
        <hashTree>
            <hashTree>
                <ThreadGroup>
                    <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
                    <stringProp name="ThreadGroup.num_threads">10</stringProp>
                    <stringProp name="ThreadGroup.ramp_time">1</stringProp>
                    <longProp name="ThreadGroup.start_time">1517853259000</longProp>
                    <longProp name="ThreadGroup.end_time">1517853259000</longProp>
                    <boolProp name="ThreadGroup.scheduler">false</boolProp>
                    <stringProp name="ThreadGroup.duration"></stringProp>
                    <stringProp name="ThreadGroup.delay"></stringProp>
                </ThreadGroup>
                <hashTree>
                    <hashTree>
                        <HTTPSamplerProxy>
                            <stringProp name="HTTPSampler.domain">www.abc.com/abc-service-api</stringProp>
                            <stringProp name="HTTPSampler.port"></stringProp>
                            <stringProp name="HTTPSampler.protocol"></stringProp>
                            <stringProp name="HTTPSampler.contentEncoding"></stringProp>
                            <stringProp name="HTTPSampler.path">/v1/test/test?debug=false</stringProp>
                            <stringProp name="HTTPSampler.method">GET</stringProp>
                            <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
                            <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
                            <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
                            <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
                            <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
                            <stringProp name="HTTPSampler.connect_timeout"></stringProp>
                            <stringProp name="HTTPSampler.response_timeout"></stringProp>
                        </HTTPSamplerProxy>
                    </hashTree>
                </hashTree>
            </hashTree>
        </hashTree>
    </TestPlan>

Код, который я использую, упомянут ниже.

    public class xmlData
        {
            [Serializable, XmlRoot("jmeterTestPlan")]
            public partial class jmeterTestPlan
            {
                private jmeterTestPlanHashTree hashTreeField;
                /// <remarks/>
                public jmeterTestPlanHashTree hashTree
                {
                    get
                    {
                        return this.hashTreeField;
                    }
                    set
                    {
                        this.hashTreeField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTree
            {
                private jmeterTestPlanHashTreeHashTree hashTreeField;
                /// <remarks/>
                public jmeterTestPlanHashTreeHashTree hashTree
                {
                    get
                    {
                        return this.hashTreeField;
                    }
                    set
                    {
                        this.hashTreeField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTree
            {
                private jmeterTestPlanHashTreeHashTreeThreadGroup threadGroupField;
                private jmeterTestPlanHashTreeHashTreeHashTree hashTreeField;
                /// <remarks/>
                public jmeterTestPlanHashTreeHashTreeThreadGroup ThreadGroup
                {
                    get
                    {
                        return this.threadGroupField;
                    }
                    set
                    {
                        this.threadGroupField = value;
                    }
                }
                /// <remarks/>
                public jmeterTestPlanHashTreeHashTreeHashTree hashTree
                {
                    get
                    {
                        return this.hashTreeField;
                    }
                    set
                    {
                        this.hashTreeField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeThreadGroup
            {
                private object[] itemsField;
                /// <remarks/>
                [System.Xml.Serialization.XmlElementAttribute("boolProp", typeof(jmeterTestPlanHashTreeHashTreeThreadGroupBoolProp))]
                [System.Xml.Serialization.XmlElementAttribute("longProp", typeof(jmeterTestPlanHashTreeHashTreeThreadGroupLongProp))]
                [System.Xml.Serialization.XmlElementAttribute("stringProp", typeof(jmeterTestPlanHashTreeHashTreeThreadGroupStringProp))]
                public object[] Items
                {
                    get
                    {
                        return this.itemsField;
                    }
                    set
                    {
                        this.itemsField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeThreadGroupBoolProp
            {
                private string nameField;
                private bool valueField;
                /// <remarks/>
                [System.Xml.Serialization.XmlAttributeAttribute()]
                public string name
                {
                    get
                    {
                        return this.nameField;
                    }
                    set
                    {
                        this.nameField = value;
                    }
                }
                /// <remarks/>
                [System.Xml.Serialization.XmlTextAttribute()]
                public bool Value
                {
                    get
                    {
                        return this.valueField;
                    }
                    set
                    {
                        this.valueField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeThreadGroupLongProp
            {
                private string nameField;
                private ulong valueField;
                /// <remarks/>
                [System.Xml.Serialization.XmlAttributeAttribute()]
                public string name
                {
                    get
                    {
                        return this.nameField;
                    }
                    set
                    {
                        this.nameField = value;
                    }
                }
                /// <remarks/>
                [System.Xml.Serialization.XmlTextAttribute()]
                public ulong Value
                {
                    get
                    {
                        return this.valueField;
                    }
                    set
                    {
                        this.valueField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeThreadGroupStringProp
            {
                private string nameField;
                private string valueField;
                /// <remarks/>
                [System.Xml.Serialization.XmlAttributeAttribute()]
                public string name
                {
                    get
                    {
                        return this.nameField;
                    }
                    set
                    {
                        this.nameField = value;
                    }
                }
                /// <remarks/>
                [System.Xml.Serialization.XmlTextAttribute()]
                public string Value
                {
                    get
                    {
                        return this.valueField;
                    }
                    set
                    {
                        this.valueField = value;
                    }
                }
            }
            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeHashTree
            {
                private jmeterTestPlanHashTreeHashTreeHashTreeHashTree hashTreeField;
                /// <remarks/>
                public jmeterTestPlanHashTreeHashTreeHashTreeHashTree hashTree
                {
                    get
                    {
                        return this.hashTreeField;
                    }
                    set
                    {
                        this.hashTreeField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeHashTreeHashTree
            {
                private jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxy hTTPSamplerProxyField;
                /// <remarks/>
                public jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxy HTTPSamplerProxy
                {
                    get
                    {
                        return this.hTTPSamplerProxyField;
                    }
                    set
                    {
                        this.hTTPSamplerProxyField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxy
            {
                private object[] itemsField;
                /// <remarks/>
                [System.Xml.Serialization.XmlElementAttribute("boolProp", typeof(jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxyBoolProp))]
                [System.Xml.Serialization.XmlElementAttribute("stringProp", typeof(jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxyStringProp))]
                public object[] Items
                {
                    get
                    {
                        return this.itemsField;
                    }
                    set
                    {
                        this.itemsField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxyBoolProp
            {
                private string nameField;
                private bool valueField;
                /// <remarks/>
                [System.Xml.Serialization.XmlAttributeAttribute()]
                public string name
                {
                    get
                    {
                        return this.nameField;
                    }
                    set
                    {
                        this.nameField = value;
                    }
                }
                /// <remarks/>
                [System.Xml.Serialization.XmlTextAttribute()]
                public bool Value
                {
                    get
                    {
                        return this.valueField;
                    }
                    set
                    {
                        this.valueField = value;
                    }
                }
            }

            /// <remarks/>
            [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
            public partial class jmeterTestPlanHashTreeHashTreeHashTreeHashTreeHTTPSamplerProxyStringProp
            {
                private string nameField;
                private string valueField;
                /// <remarks/>
                [System.Xml.Serialization.XmlAttributeAttribute()]
                public string name
                {
                    get
                    {
                        return this.nameField;
                    }
                    set
                    {
                        this.nameField = value;
                    }
                }
                /// <remarks/>
                [System.Xml.Serialization.XmlTextAttribute()]
                public string Value
                {
                    get
                    {
                        return this.valueField;
                    }
                    set
                    {
                        this.valueField = value;
                    }
                }
            }


        }

приведенный выше код дает требуемое значение с большим количеством дополнительных атрибутов, и код кажется слишком длинным. Однако мне нужны эти 4 значения. Пожалуйста, предложите лучшее решение.

Ответы [ 3 ]

0 голосов
/ 09 сентября 2018

Использовать xml linq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlData data = new XmlData(FILENAME);
        }
    }
    public class XmlData
    {
        public int? num_threads { get; set;}
        public int? ramp_time { get;set;}
        List<SamplerProxy> HTTPSamplerProxies { get;set;}

        public XmlData(string filename)
        {
            XDocument doc = XDocument.Load(filename);

            XElement threadGroup = doc.Descendants("ThreadGroup").FirstOrDefault();
            num_threads = (int?)threadGroup.Elements("stringProp").Where(x => (string)x.Attribute("name") == "ThreadGroup.num_threads").FirstOrDefault();
            ramp_time = (int?)threadGroup.Elements("stringProp").Where(x => (string)x.Attribute("name") == "ThreadGroup.ramp_time").FirstOrDefault();

            HTTPSamplerProxies = doc.Descendants("HTTPSamplerProxy").Select(x => new SamplerProxy() {
                path = (string)x.Elements("stringProp").Where(y => (string)y.Attribute("name") == "HTTPSampler.path").FirstOrDefault(),
                domain = (string)x.Elements("stringProp").Where(y => (string)y.Attribute("name") == "HTTPSampler.domain").FirstOrDefault()
            }).ToList();

        }
    }
    public class SamplerProxy
    {
        public string path { get; set; }
        public string domain { get; set; }
    }
}
0 голосов
/ 09 сентября 2018

С внешней библиотекой Cinchoo ETL - библиотекой с открытым исходным кодом, вы можете легко получить выбранные значения узлов, как показано ниже

Определить тип .NET

public class TestPlan
{
    [ChoXmlNodeRecordField(XPath = @"/ThreadGroup/stringProp[@name=""ThreadGroup.on_sample_error""]")]
    public string NumThreads { get; set; }
    [ChoXmlNodeRecordField(XPath = @"/ThreadGroup/stringProp[@name=""ThreadGroup.ramp_time""]")]
    public int RampTime { get; set; }

    [ChoXmlNodeRecordField(XPath = @"/hashTree/hashTree/HTTPSamplerProxy/stringProp[@name=""HTTPSampler.path""]")]
    public string Path { get; set; }
    [ChoXmlNodeRecordField(XPath = @"/hashTree/hashTree/HTTPSamplerProxy/stringProp[@name=""HTTPSampler.domain""]")]
    public string Domain { get; set; }
}

Затем десериализовать входной xml, используя Cinchoo ETL, как показано ниже

static void Main()
{
    using (var p = new ChoXmlReader<TestPlan>("*** XML file path ***")
        .WithXPath("/TestPlan/hashTree/hashTree")
        )
    {
        foreach (var rec in p)
            Console.WriteLine(rec.Dump());
    }
}

Выход:

-- ChoXmlReaderTest.Program+TestPlan State --
        NumThreads: continue
        RampTime: 1
        Path: /v1/test/test?debug=false
        Domain: www.abc.com/abc-service-api

Надеюсь, это поможет.

Отказ от ответственности: я автор этой библиотеки.

0 голосов
/ 09 сентября 2018

ОБНОВЛЕНО (2018-09-10)

Я обновил это, чтобы упростить его использование.

Перед тем как начать, я решил, что вам, вероятно, нужна возможность longProps в разделе HTTPSamplerProxy. Это также сделало кодирование (намного) легче и чище. Я протестировал его без longProps, просто чтобы убедиться, что он работает с существующим XML так, как вы ожидаете.

Оригинальный процесс

Обновления исходного описания выделены курсивом

Я использовал стандартное средство XSD.exe, чтобы взять исходный XML-файл (с дополнительным longProp в разделе HTTPSamplerProxy) и создать XSD. Затем я снова использовал XSD.exe для создания (очень уродливого) файла C #. На этом этапе корнем всего беспорядка является класс TestPlan. Вот что XSD.exe произвел (обновлено - единственное изменение в недавно выпущенном коде XSD.exe - это объявление пространства имен вверху) :

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class hashTree {

    private hashTreeHTTPSamplerProxy[] hTTPSamplerProxyField;

    private hashTree[] hashTree1Field;

    private hashTreeThreadGroup[] threadGroupField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("HTTPSamplerProxy", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public hashTreeHTTPSamplerProxy[] HTTPSamplerProxy {
        get {
            return this.hTTPSamplerProxyField;
        }
        set {
            this.hTTPSamplerProxyField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("hashTree")]
    public hashTree[] hashTree1 {
        get {
            return this.hashTree1Field;
        }
        set {
            this.hashTree1Field = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("ThreadGroup", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public hashTreeThreadGroup[] ThreadGroup {
        get {
            return this.threadGroupField;
        }
        set {
            this.threadGroupField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class hashTreeHTTPSamplerProxy {

    private longProp[] longPropField;

    private stringProp[] stringPropField;

    private boolProp[] boolPropField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("longProp", IsNullable = true)]
    public longProp[] longProp {
        get {
            return this.longPropField;
        }
        set {
            this.longPropField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("stringProp", IsNullable = true)]
    public stringProp[] stringProp {
        get {
            return this.stringPropField;
        }
        set {
            this.stringPropField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("boolProp", IsNullable = true)]
    public boolProp[] boolProp {
        get {
            return this.boolPropField;
        }
        set {
            this.boolPropField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)]
public partial class longProp {

    private string nameField;

    private string valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value {
        get {
            return this.valueField;
        }
        set {
            this.valueField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)]
public partial class stringProp {

    private string nameField;

    private string valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value {
        get {
            return this.valueField;
        }
        set {
            this.valueField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = true)]
public partial class boolProp {

    private string nameField;

    private string valueField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value {
        get {
            return this.valueField;
        }
        set {
            this.valueField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class hashTreeThreadGroup {

    private stringProp[] stringPropField;

    private longProp[] longPropField;

    private boolProp[] boolPropField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("stringProp", IsNullable = true)]
    public stringProp[] stringProp {
        get {
            return this.stringPropField;
        }
        set {
            this.stringPropField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("longProp", IsNullable = true)]
    public longProp[] longProp {
        get {
            return this.longPropField;
        }
        set {
            this.longPropField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("boolProp", IsNullable = true)]
    public boolProp[] boolProp {
        get {
            return this.boolPropField;
        }
        set {
            this.boolPropField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class TestPlan {

    private object[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("boolProp", typeof(boolProp), IsNullable = true)]
    [System.Xml.Serialization.XmlElementAttribute("hashTree", typeof(hashTree))]
    [System.Xml.Serialization.XmlElementAttribute("longProp", typeof(longProp), IsNullable = true)]
    [System.Xml.Serialization.XmlElementAttribute("stringProp", typeof(stringProp), IsNullable = true)]
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

Остальное в основном новое

Код, испускаемый XSD.exe, создает набор частичных классов. Я расширил частичные классы несколькими способами в отдельном исходном файле. Но прежде чем начать, я объявил интерфейс и статический рабочий класс.

public interface IGrouping {
    boolProp[] boolProp { get; }
    stringProp[] stringProp { get; }
    longProp[] longProp { get; }

    Dictionary<string, bool?> BoolProperties { get; }
    Dictionary<string, long?> LongProperties { get; }
    Dictionary<string, string> StringProperties { get; }
}

и

public static class PropertyGrouper  {
    public static void GroupProperties(IGrouping itemToGroup) {
        //has this been done before, if yes, return
        if (itemToGroup.StringProperties.Count > 0 || itemToGroup.BoolProperties.Count > 0 || itemToGroup.LongProperties.Count > 0 ) {
            return;
        }
        //otherwise
        if (itemToGroup.boolProp != null) {
            foreach (var bProp in itemToGroup.boolProp) {
                var succeeded = bool.TryParse(bProp.Value, out var bValue);
                itemToGroup.BoolProperties.Add(bProp.name, succeeded ? bValue : (bool?)null);
            }
        }
        if (itemToGroup.longProp != null) {
            foreach (var lProp in itemToGroup.longProp) {
                var succeeded = long.TryParse(lProp.Value, out var lValue);
                itemToGroup.LongProperties.Add(lProp.name, succeeded ? lValue : (long?)null);
            }
        }
        if (itemToGroup.stringProp != null) {
            foreach (var sProp in itemToGroup.stringProp) {
                itemToGroup.StringProperties.Add(sProp.name, sProp.Value);
            }
        }
    }
}

После этого я расширил каждый из классов XSD.exe. Класс TestPlan был прост - я просто добавил типизированное свойство:

public partial class TestPlan {
    [XmlIgnore]
    public hashTree HashTree => Items[0] as hashTree;
}

Классы hashTreeThreadGroup и hashTreeHTTPSamplerProxy были расширены аналогичным образом (помните, я не назвал ни один из этих классов, XSD.exe назвал их из вашего XML). Каждый из них был объявлен для реализации интерфейса IGrouping, и каждый получил 3 словаря свойств (как того требует IGrouping). Три массива в интерфейсе IGrouping были в коде XSD:

public partial class hashTreeThreadGroup : IGrouping {
    [XmlIgnore]
    public Dictionary<string, bool?> BoolProperties { get; } = new Dictionary<string, bool?>();
    [XmlIgnore]
    public Dictionary<string, long?> LongProperties { get; } = new Dictionary<string, long?>();
    [XmlIgnore]
    public Dictionary<string, string> StringProperties { get; } = new Dictionary<string, string>();
}

public partial class hashTreeHTTPSamplerProxy : IGrouping {
    [XmlIgnore]
    public Dictionary<string, bool?> BoolProperties { get; } = new Dictionary<string, bool?>();
    [XmlIgnore]
    public Dictionary<string, long?> LongProperties { get; } = new Dictionary<string, long?>();
    [XmlIgnore]
    public Dictionary<string, string> StringProperties { get; } = new Dictionary<string, string>();
}

Наконец, я расширил hashTree класс. Я добавил три типизированных свойства, каждое с пустой проверкой, чтобы все было чисто. Каждый из свойств ThreadGroupItem и HttpSamplerProxyItem получает вызов PropertyGrouper.GroupProperties. В первый раз, когда это вызывается, свойства в созданных XmlSerializer массивах свойств копируются в словари.

public partial class hashTree {
    [XmlIgnore]
    public hashTree HashTree {
        get {
            if (hashTree1 != null) {
                return hashTree1[0] as hashTree;
            } else {
                return null;
            }
        }
    }


    [XmlIgnore]
    public hashTreeThreadGroup ThreadGroupItem {
        get {
            if (ThreadGroup != null) {
                var threadGroup = ThreadGroup[0]; // as hashTreeThreadGroup;
                PropertyGrouper.GroupProperties(threadGroup);
                return threadGroup;
            } else {
                return null;
            }
        }
    }

    [XmlIgnore]
    public hashTreeHTTPSamplerProxy HttpSamplerProxyItem {
        get {
            if (HTTPSamplerProxy != null) {
                var httpSamplerProxy = HTTPSamplerProxy[0];
                PropertyGrouper.GroupProperties(httpSamplerProxy);
                return httpSamplerProxy;
            } else {
                return null;
            }
        }
    }
}

После всего этого я запустил один и тот же код.

   TestPlan result;
   using (var stream = new FileStream("source.xml", FileMode.Open, FileAccess.Read)) {
       var serializer = new XmlSerializer(typeof(TestPlan));
       result = (TestPlan)serializer.Deserialize(stream);
   }

Этот код показывает, как я получил доступ к вашим данным в первом примере.

 var numThreadsParsed = long.TryParse((((XmlSerializeForm.hashTree)result.Items[0]).hashTree1[0].ThreadGroup[0].stringProp[1].Value), out var numThreads);
 var httpSamplerPath = ((XmlSerializeForm.hashTree)result.Items[0]).hashTree1[0].hashTree1[0].hashTree1[0].HTTPSamplerProxy[0].stringProp[4].Value;

Но, с учетом нескольких простых добавлений, которые я сделал (ну, код не так уж и сложен, но получить его правильно было), доступ к свойствам намного чище:

 string numThreadsParsed = result.HashTree.HashTree.ThreadGroupItem.StringProperties["ThreadGroup.num_threads"];
 long? startTime = result.HashTree.HashTree.ThreadGroupItem.LongProperties["ThreadGroup.start_time"];
 string httpSamplerPath = result.HashTree.HashTree.HashTree.HashTree.HttpSamplerProxyItem.StringProperties["HTTPSampler.path"];
 bool? useKeepAlive = result.HashTree.HashTree.HashTree.HashTree.HttpSamplerProxyItem.BoolProperties["HTTPSampler.use_keepalive"];

Вот, пожалуйста!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...