为了账号安全,请及时绑定邮箱和手机立即绑定

使用 C# 为 XmlSerializer 初始化 XML 成员

使用 C# 为 XmlSerializer 初始化 XML 成员

C#
慕尼黑的夜晚无繁华 2022-01-09 15:05:58
我有以下 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>                        </HTTPSamplerProxy>                    </hashTree>                </hashTree>            </hashTree>        </hashTree>    </TestPlan>上面的代码给出了具有许多附加属性值的所需值,并且代码似乎也很长。但是,我需要这 4 个值。请提出任何更好的解决方案。
查看完整描述

3 回答

?
Helenr

TA贡献1780条经验 获得超4个赞

我已经更新了它以使其易于使用。


我开始之前,我决定,你可能想的可能性longProps在HTTPSamplerProxy部分。它还使编码(很多)更容易和更清洁。我已经在没有任何 longProps 的情况下对其进行了测试,只是为了确保它以您期望的方式与现有 XML 一起工作。


原流程

对原始描述的更新以斜体显示


我所做的是使用标准的 XSD.exe 工具获取您的源 XML 文件(在 HTTPSamplerProxy 部分中有一个额外的 longProp)并创建一个 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"];

给你!


查看完整回答
反对 回复 2022-01-09
?
芜湖不芜

TA贡献1796条经验 获得超7个赞

使用外部 lib 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; }

}

然后使用 Cinchoo ETL 反序列化输入 xml,如下所示


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

希望能帮助到你。


免责声明:我是这个库的作者。


查看完整回答
反对 回复 2022-01-09
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

使用 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; }

    }

}


查看完整回答
反对 回复 2022-01-09
  • 3 回答
  • 0 关注
  • 248 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号