3 回答

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"];
给你!

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
希望能帮助到你。
免责声明:我是这个库的作者。

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; }
}
}
- 3 回答
- 0 关注
- 248 浏览
添加回答
举报