I am trying to retrieve data from Zoho API and then I want to Deserialize a returned data in an object.
The XML structure:
<response uri="/crm/private/xml/Potentials/getSearchRecords">
<result>
<Potentials>
<row no="1">
<FL val="POTENTIALID">0000000000000</FL>
<FL val="SMOWNERID">000000000000</FL>
.......
</row>
<row no="2">
.......
</row>
</Potentials>
</result>
</response>
And here what I tried but didn't succeed.
[Serializable()]
public class ZohoXML
{
public ZohoXML() { }
[XmlElement("POTENTIALID")]
public string POTENTIALID { get; set; }
........
}
[XmlRoot("response")]
public class Response
{
[XmlElement("result")]
public Result[] ResultList { get; set; }
}
public class Result
{
[XmlArray("Potentials"), XmlArrayItem("row")]
public Row[] RowList { get; set; }
}
[XmlRoot("row")]
public class Row
{
[XmlArray("Potentials")]
[XmlArrayItem("row", typeof(ZohoXML))]
public ZohoXML[] ZohoXML { get; set; }
}
And this is how I deserialize:
Response ZohoXMLCollection = null;
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Response));
StreamReader reader = new StreamReader(strFile);
ZohoXMLCollection = (Response)serializer.Deserialize(reader);
reader.Close();
Can anybody please help on identifying an issue in the code ?
If you are using a newer version of VS you can use Edit > Paste Special > Paste XML as Classes in the edit menu. Assuming your XML structure is correct this will give you:
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class response
{
private responseResult resultField;
private string uriField;
/// <remarks/>
public responseResult result
{
get
{
return this.resultField;
}
set
{
this.resultField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string uri
{
get
{
return this.uriField;
}
set
{
this.uriField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class responseResult
{
private responseResultRow[] potentialsField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("row", IsNullable = false)]
public responseResultRow[] Potentials
{
get
{
return this.potentialsField;
}
set
{
this.potentialsField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class responseResultRow
{
private responseResultRowFL[] flField;
private byte noField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("FL")]
public responseResultRowFL[] FL
{
get
{
return this.flField;
}
set
{
this.flField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte no
{
get
{
return this.noField;
}
set
{
this.noField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class responseResultRowFL
{
private string valField;
private byte valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string val
{
get
{
return this.valField;
}
set
{
this.valField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public byte Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
You will want to clean up the names but for now this is fine.
Then your de-serialization will look like this:
XmlSerializer serializer = new XmlSerializer(typeof(response));
response res = new response();
using (StreamReader reader = new StreamReader(fileLocation))
{
res = serializer.Deserialize(reader) as response;
}
Note that StreamReader implements the IDisposable interface so should be used within a using block to ensure automatic disposable of resources.
Related
I want to create an API in .net core which accept XML request and gives response in XML only.
I have searched and created sample but when I hit request to the API with XML request it does not work.
Debugger did not come up to the controller.
I have also added below the line of code in the configure services of the startup.cs class.
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
options.InputFormatters.Insert(0, new XDocumentInputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters();
The POST method have written in the controller as below.
[Produces("application/xml")]
[ProducesResponseType(typeof(CustomerDetails), (int)HttpStatusCode.OK)]
[HttpPost("CustomerDetails", Name = "CustomerDetails")]
public IActionResult CustomerDetails([FromBody] CustomerDetails CustReq)
{
var resp = new CustomerDetails
{
BankId="1234567"
};
return Ok(resp);
}
Processing my request from Postman getting an error.
An unhandled exception occurred while processing the request.
InvalidCastException: Unable to cast object of type 'System.Xml.Linq.XDocument' to type 'CustomerValidationAPI.Models.CustomerDetails'.
Below is my XML request I want to process.
It also has multiple nodes how can we handle.
<?xml version="1.0" encoding="UTF-8"?>
<FIXML xmlns="http://www.finacle.com/fixml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.finacle.com/fixml
executeFinacleScript.xsd">
<Header>
<RequestHeader>
<MessageKey>
<RequestUUID>FEBA_1553756445880</RequestUUID>
<ServiceRequestId>executeFinacleScript</ServiceRequestId>
<ServiceRequestVersion>10.2</ServiceRequestVersion>
<ChannelId>COR</ChannelId>
</MessageKey>
<RequestMessageInfo>
<BankId>04</BankId>
<TimeZone>GMT+05:00</TimeZone>
<EntityId />
<EntityType />
<ArmCorrelationId />
<MessageDateTime>2019-03-28T11:00:45.880</MessageDateTime>
</RequestMessageInfo>
<Security>
<Token>
<PasswordToken>
<UserId>11111</UserId>
<Password />
</PasswordToken>
</Token>
<FICertToken />
<RealUserLoginSessionId />
<RealUser />
<RealUserPwd />
<SSOTransferToken />
</Security>
</RequestHeader>
</Header>
<Body>
<executeFinacleScriptRequest>
<ExecuteFinacleScriptInputVO>
<requestId>validateAcct.scr</requestId>
</ExecuteFinacleScriptInputVO>
<executeFinacleScript_CustomData>
<ACCT_NUM>01122507576</ACCT_NUM>
<PHONE_NUM>59887834</PHONE_NUM>
<NIC>G2105493001653</NIC>
</executeFinacleScript_CustomData>
</executeFinacleScriptRequest>
</Body>
</FIXML>
Customer Details Model Have created as below
public class CustomerDetails
{
[Required]
public string RequestUUID { get; set; }
[Required]
public string ServiceRequestId { get; set; }
[Required]
public string ServiceRequestVersion { get; set; }
[Required]
public string ChannelId { get; set; }
[Required]
public string BankId { get; set; }
[Required]
public string TimeZone { get; set; }
public string EntityId { get; set; }
public string EntityType { get; set; }
public string ArmCorrelationId { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime MessageDateTime { get; set; }
[Required]
public string Password { get; set; }
public string FICertToken { get; set; }
public string RealUserLoginSessionId { get; set; }
public string RealUser { get; set; }
public string RealUserPwd { get; set; }
public string SSOTransferToken { get; set; }
[Required]
public string requestId { get; set; }
[Required]
public string ACCT_NUM { get; set; }
[Required]
public string PHONE_NUM { get; set; }
[Required]
public string NIC { get; set; }
}
My startUp class
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
options.InputFormatters.Insert(0, new XDocumentInputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters();
}
XDocumentInputFormatter in class have taken as below..
public class XDocumentInputFormatter : InputFormatter, IInputFormatter, IApiRequestFormatMetadataProvider
{
public XDocumentInputFormatter()
{
SupportedMediaTypes.Add("application/xml");
}
protected override bool CanReadType(Type type)
{
if (type.IsAssignableFrom(typeof(XDocument))) return true;
return base.CanReadType(type);
}
//public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
//{
// var xmlDoc = await XDocument.LoadAsync(context.HttpContext.Request.Body, LoadOptions.None, CancellationToken.None);
// return InputFormatterResult.Success(xmlDoc);
//}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
// Use StreamReader to convert any encoding to UTF-16 (default C# and sql Server).
using (var streamReader = new StreamReader(context.HttpContext.Request.Body))
{
var xmlDoc = await XDocument.LoadAsync(streamReader, LoadOptions.None, CancellationToken.None);
return InputFormatterResult.Success(xmlDoc);
}
}
}
ERROR I AM GETTING NOW
An unhandled exception occurred while processing the request.
InvalidOperationException: http://www.finacle.com/fixml'> was not expected.
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderTestClass.Read3_TestClass()
InvalidOperationException: There is an error in XML document (1, 174).
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
Created the Class from XML as below
public class XMLClass
{
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.finacle.com/fixml", IsNullable = false)]
public partial class FIXML
{
private FIXMLHeader headerField;
private FIXMLBody bodyField;
/// <remarks/>
public FIXMLHeader Header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
/// <remarks/>
public FIXMLBody Body
{
get
{
return this.bodyField;
}
set
{
this.bodyField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeader
{
private FIXMLHeaderRequestHeader requestHeaderField;
/// <remarks/>
public FIXMLHeaderRequestHeader RequestHeader
{
get
{
return this.requestHeaderField;
}
set
{
this.requestHeaderField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeader
{
private FIXMLHeaderRequestHeaderMessageKey messageKeyField;
private FIXMLHeaderRequestHeaderRequestMessageInfo requestMessageInfoField;
private FIXMLHeaderRequestHeaderSecurity securityField;
/// <remarks/>
public FIXMLHeaderRequestHeaderMessageKey MessageKey
{
get
{
return this.messageKeyField;
}
set
{
this.messageKeyField = value;
}
}
/// <remarks/>
public FIXMLHeaderRequestHeaderRequestMessageInfo RequestMessageInfo
{
get
{
return this.requestMessageInfoField;
}
set
{
this.requestMessageInfoField = value;
}
}
/// <remarks/>
public FIXMLHeaderRequestHeaderSecurity Security
{
get
{
return this.securityField;
}
set
{
this.securityField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeaderMessageKey
{
private string requestUUIDField;
private string serviceRequestIdField;
private decimal serviceRequestVersionField;
private string channelIdField;
/// <remarks/>
public string RequestUUID
{
get
{
return this.requestUUIDField;
}
set
{
this.requestUUIDField = value;
}
}
/// <remarks/>
public string ServiceRequestId
{
get
{
return this.serviceRequestIdField;
}
set
{
this.serviceRequestIdField = value;
}
}
/// <remarks/>
public decimal ServiceRequestVersion
{
get
{
return this.serviceRequestVersionField;
}
set
{
this.serviceRequestVersionField = value;
}
}
/// <remarks/>
public string ChannelId
{
get
{
return this.channelIdField;
}
set
{
this.channelIdField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeaderRequestMessageInfo
{
private byte bankIdField;
private string timeZoneField;
private object entityIdField;
private object entityTypeField;
private object armCorrelationIdField;
private System.DateTime messageDateTimeField;
/// <remarks/>
public byte BankId
{
get
{
return this.bankIdField;
}
set
{
this.bankIdField = value;
}
}
/// <remarks/>
public string TimeZone
{
get
{
return this.timeZoneField;
}
set
{
this.timeZoneField = value;
}
}
/// <remarks/>
public object EntityId
{
get
{
return this.entityIdField;
}
set
{
this.entityIdField = value;
}
}
/// <remarks/>
public object EntityType
{
get
{
return this.entityTypeField;
}
set
{
this.entityTypeField = value;
}
}
/// <remarks/>
public object ArmCorrelationId
{
get
{
return this.armCorrelationIdField;
}
set
{
this.armCorrelationIdField = value;
}
}
/// <remarks/>
public System.DateTime MessageDateTime
{
get
{
return this.messageDateTimeField;
}
set
{
this.messageDateTimeField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeaderSecurity
{
private FIXMLHeaderRequestHeaderSecurityToken tokenField;
private object fICertTokenField;
private object realUserLoginSessionIdField;
private object realUserField;
private object realUserPwdField;
private object sSOTransferTokenField;
/// <remarks/>
public FIXMLHeaderRequestHeaderSecurityToken Token
{
get
{
return this.tokenField;
}
set
{
this.tokenField = value;
}
}
/// <remarks/>
public object FICertToken
{
get
{
return this.fICertTokenField;
}
set
{
this.fICertTokenField = value;
}
}
/// <remarks/>
public object RealUserLoginSessionId
{
get
{
return this.realUserLoginSessionIdField;
}
set
{
this.realUserLoginSessionIdField = value;
}
}
/// <remarks/>
public object RealUser
{
get
{
return this.realUserField;
}
set
{
this.realUserField = value;
}
}
/// <remarks/>
public object RealUserPwd
{
get
{
return this.realUserPwdField;
}
set
{
this.realUserPwdField = value;
}
}
/// <remarks/>
public object SSOTransferToken
{
get
{
return this.sSOTransferTokenField;
}
set
{
this.sSOTransferTokenField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeaderSecurityToken
{
private FIXMLHeaderRequestHeaderSecurityTokenPasswordToken passwordTokenField;
/// <remarks/>
public FIXMLHeaderRequestHeaderSecurityTokenPasswordToken PasswordToken
{
get
{
return this.passwordTokenField;
}
set
{
this.passwordTokenField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLHeaderRequestHeaderSecurityTokenPasswordToken
{
private ushort userIdField;
private object passwordField;
/// <remarks/>
public ushort UserId
{
get
{
return this.userIdField;
}
set
{
this.userIdField = value;
}
}
/// <remarks/>
public object Password
{
get
{
return this.passwordField;
}
set
{
this.passwordField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLBody
{
private FIXMLBodyExecuteFinacleScriptRequest executeFinacleScriptRequestField;
/// <remarks/>
public FIXMLBodyExecuteFinacleScriptRequest executeFinacleScriptRequest
{
get
{
return this.executeFinacleScriptRequestField;
}
set
{
this.executeFinacleScriptRequestField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLBodyExecuteFinacleScriptRequest
{
private FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO executeFinacleScriptInputVOField;
private FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData executeFinacleScript_CustomDataField;
/// <remarks/>
public FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO ExecuteFinacleScriptInputVO
{
get
{
return this.executeFinacleScriptInputVOField;
}
set
{
this.executeFinacleScriptInputVOField = value;
}
}
/// <remarks/>
public FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData executeFinacleScript_CustomData
{
get
{
return this.executeFinacleScript_CustomDataField;
}
set
{
this.executeFinacleScript_CustomDataField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScriptInputVO
{
private string requestIdField;
/// <remarks/>
public string requestId
{
get
{
return this.requestIdField;
}
set
{
this.requestIdField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.finacle.com/fixml")]
public partial class FIXMLBodyExecuteFinacleScriptRequestExecuteFinacleScript_CustomData
{
private uint aCCT_NUMField;
private uint pHONE_NUMField;
private string nICField;
/// <remarks/>
public uint ACCT_NUM
{
get
{
return this.aCCT_NUMField;
}
set
{
this.aCCT_NUMField = value;
}
}
/// <remarks/>
public uint PHONE_NUM
{
get
{
return this.pHONE_NUMField;
}
set
{
this.pHONE_NUMField = value;
}
}
/// <remarks/>
public string NIC
{
get
{
return this.nICField;
}
set
{
this.nICField = value;
}
}
}
}
public class Token
{
public PasswordToken PasswordToken{get;set;}
}
public class PasswordToken
{
public string UserId{get;set;}
public string Password{get;set;}
}
public class Body
{
public executeFinacleScriptRequest executeFinacleScriptRequest{get;set;}
}
public class executeFinacleScriptRequest
{
public ExecuteFinacleScriptInputVO ExecuteFinacleScriptInputVO{get;set;}
public executeFinacleScript_CustomData executeFinacleScript_CustomData{get;set;}
}
public class ExecuteFinacleScriptInputVO
{
public string requestId{get;set;}
}
public class executeFinacleScript_CustomData
{
public string ACCT_NUM{get;set;}
public string PHONE_NUM{get;set;}
public string NIC{get;set;}
}
the result is serialized based on what the requester requested! if you want xml just put ja corresponding header! and why [FromBody]XElement xml ? cant you use a normal model?
If Your API need request in XML. Below are things need to consider
1. In .ent core add below code in ConfigureServices method of Startup.cs Class
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters();
Create XML Data class by just simply copy your XML request and in the visual studio ..select paste special from edit menu and select paste XML as classes. It will generate classes as per your XML.
Now you this class as [FromBody] YourClassName request in post method. Do include produce annotation as application/xml above your post method
In ASP.NET Core, everything is highly modular, so you only add the functionality you need to your application. Consequently, there's a separate NuGet package for the XML formatters that you need to add to your .csproj file - Microsoft.AspNetCore.Mvc.Formatters.Xml
<PackageReference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" Version="1.1.3" />
Adding the package to your project lights up an extension method on the IMvcBuilder instance returned by the call to services.AddMvc(). The AddXmlSerializerFormatters() method adds both input and output formatters, so you can serialise objects to and from XML.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddXmlSerializerFormatters();
}
Alternatively, if you only want to be able to format results as XML, but don't need to be able to read XML from a request body, you can just add the output formatter instead:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
});
}
For Supporting XML as Input
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.FormatterMappings.SetMediaTypeMappingForFormat
("xml", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat
("config", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat
("js", MediaTypeHeaderValue.Parse("application/json"));
})
.AddXmlSerializerFormatters();
I would like to be able to 'do things' to the Vehicles in the XML file. Ideally I want to iterate through all the vehicles and do a calculation on their price, and change whether they are OnSale. These values would then be displayed in the UI. My code deserializes the XML file but I am unable to access any of the attributes for the Vehicle. I do not need to serialize the objects back to XML.
I have tried to Console.WriteLine the Price, however when I run the code it is returned as 0. Should I be creating an Array of ResponseGeographyVendorRegionVehicle? and then somehow adding objects of that type to the array?
This is the XML File:
<?xml version="1.0" encoding="utf-8" ?>
<Response>
<Geography>
<Vendor id="JOHN">
<Region id="1"></Region>
<Region id="2">
<Vehicle Make="HONDA" Fuel="Gas" Price="12000" OnSale="Y" Account="JOHNH" />
<Vehicle Make="ACURA" Fuel="Gas" Price="14100" OnSale="Y" Account="JOHNH" />
<Vehicle Make="TOYOTA" Fuel="Gas" Price="8000" OnSale="N" Account="JOHNH" />
<Vehicle Make="HYUNDAI" Fuel="Gas" Price="13000" OnSale="Y" Account="JOHNH" />
<Vehicle Make="INFINITY" Fuel="Gas" Price="16000" OnSale="N" Account="JOHNH" />
</Region>
<Region id="3"></Region>
<Region id="4"></Region>
</Vendor>
</Geography>
</Response>
This is my Program.cs:
namespace XMLDeserializeExample
{
class Program
{
static void Main(string[] args)
{
string path = #"c:\XMLFile1.xml";
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "Response";
XmlSerializer ser = new XmlSerializer(typeof(ResponseGeographyVendorRegionVehicle), xRoot);
ResponseGeographyVendorRegionVehicle i;
using (Stream reader = new FileStream(path,FileMode.Open))
{
i = (ResponseGeographyVendorRegionVehicle)ser.Deserialize(reader);
Console.WriteLine(i.Price);
Console.ReadLine();
}
}
}
}
This is the Paste Special Response.CS file that was created:
namespace XMLDeserializeExample
{
}
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Response
{
private ResponseGeography geographyField;
/// <remarks/>
public ResponseGeography Geography
{
get
{
return this.geographyField;
}
set
{
this.geographyField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeography
{
private ResponseGeographyVendor vendorField;
/// <remarks/>
public ResponseGeographyVendor Vendor
{
get
{
return this.vendorField;
}
set
{
this.vendorField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendor
{
private ResponseGeographyVendorRegion[] regionField;
private string idField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Region")]
public ResponseGeographyVendorRegion[] Region
{
get
{
return this.regionField;
}
set
{
this.regionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendorRegion
{
private ResponseGeographyVendorRegionVehicle[] vehicleField;
private byte idField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Vehicle")]
public ResponseGeographyVendorRegionVehicle[] Vehicle
{
get
{
return this.vehicleField;
}
set
{
this.vehicleField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public byte id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class ResponseGeographyVendorRegionVehicle
{
private string makeField;
private string fuelField;
private ushort priceField;
private string onSaleField;
private string accountField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Make
{
get
{
return this.makeField;
}
set
{
this.makeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Fuel
{
get
{
return this.fuelField;
}
set
{
this.fuelField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public ushort Price
{
get
{
return this.priceField;
}
set
{
this.priceField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string OnSale
{
get
{
return this.onSaleField;
}
set
{
this.onSaleField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Account
{
get
{
return this.accountField;
}
set
{
this.accountField = value;
}
}
}
Please let me know how I can better explain myself. Apologies if none of this makes sense- welcome to my weekend lol.
Thank you.
As your xml-root is obviously a Response instead of a ResponseGeographyVendor you have to de-serialize to that type:
string path = #"c:\XMLFile1.xml";
XmlSerializer ser = new XmlSerializer(typeof(response);
ResponseGeographyVendor i;
using (Stream reader = new FileStream(path,FileMode.Open))
{
i = ((Response)ser.Deserialize(reader)).Geography.Vendor;
Console.WriteLine(i.Price);
Console.ReadLine();
}
A serializer will only work on the entire xml-document. You can´t just write or read parts of it. So just use the xml, serialize it to an instance of Response and get its Geography-member.
Now you can easily get the 3rd Vehicle within the second Region:
var vehicle = i.Region[1].Vehicle[2];
Notice that you don´t need to provide the xml-root yourself.
You'll want to use the XML Serializer that's built into .Net.
First create a class to represent the XML document data:
public class Response
{
public Geography Geography {get; set;}
}
public class Geography
{
public Vendor Vendor{get;set;}
}
public class Vendor
{
public List<Region> Regions {get;set;}
}
public class Region
{
}
and so on.
Then read the xml as a string and deserialize it:
string myXml = File.ReadAsStringAsync(filepath).Result;
XmlSerializer ser = new XmlSerializer(typeof(Response));
using (TextReader reader = new StringReader(myXml)
{
Response myResponse = ser.Deserialize(reader);
}
Then you can iterate through all the properties and stuff on the Geography object.
I am trying to deserialize the following XML
<?xml version="1.0" encoding="UTF-8"?>
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/CM/envelope">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>DRUG_DATA</Class>
<Qualifier>response</Qualifier>
<Function>submit</Function>
<CorrelationID>BD694DAAA26AA6068EAAAE5C7746CE54</CorrelationID>
<Transformation>XML</Transformation>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID />
<Authentication>
<Method />
<Role />
<Value />
</Authentication>
</IDAuthentication>
</SenderDetails>
</Header>
<GovTalkDetails>
<Keys>
<Key Type="SpokeName" />
</Keys>
</GovTalkDetails>
<Body>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope">
<S:Body>
<ns2:getGenericDrugsResponse xmlns:ns2="http://webservice.sirkb/">
<return>
<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
<GENERIC_DRUG_ID>147</GENERIC_DRUG_ID>
<GENERIC_DRUG_NAME>Amoxicilline 125mg/5ml - 60ml</GENERIC_DRUG_NAME>
</DRUG>
<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
<GENERIC_DRUG_ID>149</GENERIC_DRUG_ID>
<GENERIC_DRUG_NAME>Amoxicilline 250mg/5ml - 60ml</GENERIC_DRUG_NAME>
</DRUG>
<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
<DOSAGE>10mg/5ml</DOSAGE>
<GENERIC_DRUG_ID>2312</GENERIC_DRUG_ID>
<GENERIC_DRUG_NAME>Vinorelbine (as vinorelbine tartrate)</GENERIC_DRUG_NAME>
<PHARMACEUTICAL_FORM>concentrate for solution for infusion</PHARMACEUTICAL_FORM>
</DRUG>
<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
<DOSAGE>100 u/ml (approximately 0.58mg)</DOSAGE>
<GENERIC_DRUG_ID>2313</GENERIC_DRUG_ID>
<GENERIC_DRUG_NAME>Laronidase</GENERIC_DRUG_NAME>
<PHARMACEUTICAL_FORM>concentrate for solution for infusion</PHARMACEUTICAL_FORM>
</DRUG>
<RETURN_STATUS>SUCCESS</RETURN_STATUS>
</return>
</ns2:getGenericDrugsResponse>
</S:Body>
</S:Envelope>
</Body>
</GovTalkMessage>
I have generated the classes through Paste XML as Classes feature of Visual Studio 2017. (Using the xsd.exe is the same) I have not changed the generated classes.
They have the following form:
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope", IsNullable = false)]
public partial class GovTalkMessage
{
private decimal envelopeVersionField;
private GovTalkMessageHeader headerField;
private GovTalkMessageGovTalkDetails govTalkDetailsField;
private GovTalkMessageBody bodyField;
/// <remarks/>
public decimal EnvelopeVersion
{
get
{
return this.envelopeVersionField;
}
set
{
this.envelopeVersionField = value;
}
}
/// <remarks/>
public GovTalkMessageHeader Header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
/// <remarks/>
public GovTalkMessageGovTalkDetails GovTalkDetails
{
get
{
return this.govTalkDetailsField;
}
set
{
this.govTalkDetailsField = value;
}
}
/// <remarks/>
public GovTalkMessageBody Body
{
get
{
return this.bodyField;
}
set
{
this.bodyField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeader
{
private GovTalkMessageHeaderMessageDetails messageDetailsField;
private GovTalkMessageHeaderSenderDetails senderDetailsField;
/// <remarks/>
public GovTalkMessageHeaderMessageDetails MessageDetails
{
get
{
return this.messageDetailsField;
}
set
{
this.messageDetailsField = value;
}
}
/// <remarks/>
public GovTalkMessageHeaderSenderDetails SenderDetails
{
get
{
return this.senderDetailsField;
}
set
{
this.senderDetailsField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderMessageDetails
{
private string classField;
private string qualifierField;
private string functionField;
private string correlationIDField;
private string transformationField;
/// <remarks/>
public string Class
{
get
{
return this.classField;
}
set
{
this.classField = value;
}
}
/// <remarks/>
public string Qualifier
{
get
{
return this.qualifierField;
}
set
{
this.qualifierField = value;
}
}
/// <remarks/>
public string Function
{
get
{
return this.functionField;
}
set
{
this.functionField = value;
}
}
/// <remarks/>
public string CorrelationID
{
get
{
return this.correlationIDField;
}
set
{
this.correlationIDField = value;
}
}
/// <remarks/>
public string Transformation
{
get
{
return this.transformationField;
}
set
{
this.transformationField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetails
{
private GovTalkMessageHeaderSenderDetailsIDAuthentication iDAuthenticationField;
/// <remarks/>
public GovTalkMessageHeaderSenderDetailsIDAuthentication IDAuthentication
{
get
{
return this.iDAuthenticationField;
}
set
{
this.iDAuthenticationField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetailsIDAuthentication
{
private object senderIDField;
private GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication authenticationField;
/// <remarks/>
public object SenderID
{
get
{
return this.senderIDField;
}
set
{
this.senderIDField = value;
}
}
/// <remarks/>
public GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication Authentication
{
get
{
return this.authenticationField;
}
set
{
this.authenticationField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageHeaderSenderDetailsIDAuthenticationAuthentication
{
private object methodField;
private object roleField;
private object valueField;
/// <remarks/>
public object Method
{
get
{
return this.methodField;
}
set
{
this.methodField = value;
}
}
/// <remarks/>
public object Role
{
get
{
return this.roleField;
}
set
{
this.roleField = value;
}
}
/// <remarks/>
public object Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetails
{
private GovTalkMessageGovTalkDetailsKeys keysField;
/// <remarks/>
public GovTalkMessageGovTalkDetailsKeys Keys
{
get
{
return this.keysField;
}
set
{
this.keysField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetailsKeys
{
private GovTalkMessageGovTalkDetailsKeysKey keyField;
/// <remarks/>
public GovTalkMessageGovTalkDetailsKeysKey Key
{
get
{
return this.keyField;
}
set
{
this.keyField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageGovTalkDetailsKeysKey
{
private string typeField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Type
{
get
{
return this.typeField;
}
set
{
this.typeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class GovTalkMessageBody
{
private Envelope envelopeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Envelope Envelope
{
get
{
return this.envelopeField;
}
set
{
this.envelopeField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.w3.org/2003/05/soap-envelope", IsNullable = false)]
public partial class Envelope
{
private EnvelopeBody bodyField;
/// <remarks/>
public EnvelopeBody Body
{
get
{
return this.bodyField;
}
set
{
this.bodyField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public partial class EnvelopeBody
{
private getGenericDrugsResponse getGenericDrugsResponseField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://webservice.sirkb/")]
public getGenericDrugsResponse getGenericDrugsResponse
{
get
{
return this.getGenericDrugsResponseField;
}
set
{
this.getGenericDrugsResponseField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://webservice.sirkb/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://webservice.sirkb/", IsNullable = false)]
public partial class getGenericDrugsResponse
{
private #return returnField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public #return #return
{
get
{
return this.returnField;
}
set
{
this.returnField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope", IsNullable = false)]
public partial class #return
{
private returnDRUG[] dRUGField;
private string rETURN_STATUSField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DRUG")]
public returnDRUG[] DRUG
{
get
{
return this.dRUGField;
}
set
{
this.dRUGField = value;
}
}
/// <remarks/>
public string RETURN_STATUS
{
get
{
return this.rETURN_STATUSField;
}
set
{
this.rETURN_STATUSField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class returnDRUG
{
private string dOSAGEField;
private ushort gENERIC_DRUG_IDField;
private string gENERIC_DRUG_NAMEField;
private string pHARMACEUTICAL_FORMField;
/// <remarks/>
public string DOSAGE
{
get
{
return this.dOSAGEField;
}
set
{
this.dOSAGEField = value;
}
}
/// <remarks/>
public ushort GENERIC_DRUG_ID
{
get
{
return this.gENERIC_DRUG_IDField;
}
set
{
this.gENERIC_DRUG_IDField = value;
}
}
/// <remarks/>
public string GENERIC_DRUG_NAME
{
get
{
return this.gENERIC_DRUG_NAMEField;
}
set
{
this.gENERIC_DRUG_NAMEField = value;
}
}
/// <remarks/>
public string PHARMACEUTICAL_FORM
{
get
{
return this.pHARMACEUTICAL_FORMField;
}
set
{
this.pHARMACEUTICAL_FORMField = value;
}
}
}
I get the following error:
System.InvalidOperationException: 'There is an error in XML document (33, 14).'
Inner Exception
InvalidOperationException: The specified type was not recognized:
name='genericDrug', namespace='http://webservice.sirkb/', at http://www.govtalk.gov.uk/CM/envelope'>.
I have noticed from this thread that if I remove xsi:type="ns2:genericDrug" from the XML file I can deserialize the XML. I can't modify the XML because it is the response I get for the request. It is not a good practice to do a string replace on XML, so I am looking for a better solution.
This might be a duplicate question from this one, but since I am not able to solve the problem I am posting it again because it is difficult to get help in the comment section.
Based on the above question I have tried to change the annotation of public partial class returnDRUG
from
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
to
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.w3.org/2001/XMLSchema-instance", TypeName = "genericDrug")]
but still cant parse the XML.
The parsing code is simple
var deserializer = new XmlSerializer(typeof(GovTalkMessage));
TextReader textReader = new StreamReader("drug.xml"); //saved response in file for simplicity
GovTalkMessage response;
response = (GovTalkMessage)deserializer.Deserialize(textReader);
textReader.Close();
What can I do to deserialize the XML in the GovTalkMessage object?
You need to change the decoration on the returnDRUG class
from this
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public partial class returnDRUG
to this
[System.Xml.Serialization.XmlTypeAttribute(TypeName = "genericDrug", Namespace = "http://webservice.sirkb/")]
public partial class returnDRUG
Specify it's type as "genericDrug", and the crucial bit, correct it's namespace to "http://webservice.sirkb/"
I've just used you code and managed to de-serialize using this change.
The explanation is that if you take a look at the definition of DRUG you can see that it's type is defined as "genericDRUG" in the namespace alias "ns2"
<DRUG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:genericDrug">
if you look at the definition of the ns2 alias you can see that it's "http://webservice.sirkb/"
<ns2:getGenericDrugsResponse xmlns:ns2="http://webservice.sirkb/">
Some addition to prevent default values for DRUG objects
Every property of the returnDrug class should have the namespace http://www.govtalk.gov.uk/CM/envelope.
The complete class should have the following form:
[System.Xml.Serialization.XmlTypeAttribute(TypeName = "genericDrug", Namespace = "http://webservice.sirkb/")]
public partial class returnDRUG
{
private string dOSAGEField;
private ushort gENERIC_DRUG_IDField;
private string gENERIC_DRUG_NAMEField;
private string pHARMACEUTICAL_FORMField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public string DOSAGE
{
get
{
return this.dOSAGEField;
}
set
{
this.dOSAGEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public ushort GENERIC_DRUG_ID
{
get
{
return this.gENERIC_DRUG_IDField;
}
set
{
this.gENERIC_DRUG_IDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public string GENERIC_DRUG_NAME
{
get
{
return this.gENERIC_DRUG_NAMEField;
}
set
{
this.gENERIC_DRUG_NAMEField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "http://www.govtalk.gov.uk/CM/envelope")]
public string PHARMACEUTICAL_FORM
{
get
{
return this.pHARMACEUTICAL_FORMField;
}
set
{
this.pHARMACEUTICAL_FORMField = value;
}
}
}
I have below XML and need to deserialized to get the value of "ThreadGroup.num_threads","ThreadGroup.ramp_time","HTTPSampler.path" and "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>
The code I am using mentioned below.
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;
}
}
}
}
the above code is giving required value with a lot of additional attributes value and the code seems lengthy too. However, I need those 4 value. Please suggest any better solution.
UPDATED (2018-09-10)
I've updated this to get it easy to use.
Before I started, I decided that you probably wanted the possibility of longProps in the HTTPSamplerProxy section. It also made the coding (much) easier and cleaner. I've tested it without any longProps just to make sure it worked with the existing XML the way you'd expect.
The original process
The updates to the original description are italicized
What I did was to use the standard XSD.exe tool to take your source XML file (with an extra longProp in the HTTPSamplerProxy section) and create an XSD. Then I used XSD.exe again to create a (very ugly) C# file. At that point, the root of the whole mess is the TestPlan class. Here's what XSD.exe produced (updated - the only change to the newly-emitted XSD.exe code was a namespace declaration at the top):
/// <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;
}
}
}
The rest of this is mostly new
The code emitted by XSD.exe creates a set of partial classes. I extended the partial classes in a few ways in a separate source file. But, before I started, I declared an interface and a static worker class.
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; }
}
and
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);
}
}
}
}
With those in place, I extended each of the XSD.exe-emitted classes. The TestPlan class was easy - I just added a typed property:
public partial class TestPlan {
[XmlIgnore]
public hashTree HashTree => Items[0] as hashTree;
}
The hashTreeThreadGroup and hashTreeHTTPSamplerProxy classes were extended in the same way (remember, I didn't name any of these classes, XSD.exe named them from your XML) . Each was declared to implement the IGrouping interface, and each got 3 dictionaries of properties (as required by IGrouping). The three arrays in the IGrouping interface were in the XSD-emitted code:
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>();
}
Finally, I extended hashTree class. I added three typed properties, each with a null check to make things clean. The ThreadGroupItem and HttpSamplerProxyItem properties each get a call to PropertyGrouper.GroupProperties. The first time this is called, the properties in the XmlSerializer-created property arrays are copied into Dictionaries.
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;
}
}
}
}
With that all in place, I ran the same code.
TestPlan result;
using (var stream = new FileStream("source.xml", FileMode.Open, FileAccess.Read)) {
var serializer = new XmlSerializer(typeof(TestPlan));
result = (TestPlan)serializer.Deserialize(stream);
}
This code is how I accessed your data with my first example.
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;
But, with the few simple additions I made (well, the code isn't that complicated, but getting it right was), accessing the properties is much cleaner:
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"];
There you go!
With external lib Cinchoo ETL - an open source library, you can grab the chosen node values easily as below
Define .NET type
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; }
}
Then deserialize the input xml using Cinchoo ETL as below
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());
}
}
Output:
-- ChoXmlReaderTest.Program+TestPlan State --
NumThreads: continue
RampTime: 1
Path: /v1/test/test?debug=false
Domain: www.abc.com/abc-service-api
Hope it helps.
Disclaimer: I'm the author of this library.
Use 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; }
}
}
I'm trying to deserialize the below XML but the process seems not to be working...
Here's what I get when I display the values in a PropertyGrid control after deserializing the XML:
As you can see, the elements under Header has no values.
Can you please help to check what's wrong with the codes?
Message class:
namespace MyProject
{
[XmlRoot(ElementName="Header")]
public class Header {
[XmlElement(ElementName="Sender")]
public string Sender { get; set; }
[XmlElement(ElementName="Receiver")]
public string Receiver { get; set; }
[XmlElement(ElementName="MessageID")]
public string MessageID { get; set; }
[XmlElement(ElementName="CreationDateTime")]
public string CreationDateTime { get; set; }
[XmlAttribute(AttributeName="version")]
public string Version { get; set; }
}
[XmlRoot(ElementName="Message", Namespace="http://example.com")]
public class Message {
private Header _header = new Header();
[XmlElement(ElementName="Header")]
[TypeConverter(typeof(ConverterExpandableObject))]
public Header Header
{
get { return _header; }
set { _header = value; }
}
[XmlAttribute(AttributeName="ns", Namespace="http://www.w3.org/2000/xmlns/")]
public string Ns { get; set; }
}
}
Method to deserialize the XML:
void DeserializeMessage()
{
string messageString = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\Message.xml";
if (File.Exists(messageString))
{
XmlSerializer serializer = new XmlSerializer(typeof(Message));
StreamReader reader = new StreamReader(messageString);
Message m = (Message)serializer.Deserialize(reader);
reader.Close();
propertyGrid1.SelectedObject = m;
}
}
and the XML itself:
<?xml version="1.0" encoding="UTF-8"?>
<ns:Message xmlns:ns="http://example.com">
<Header version="1.0">
<Sender>3015207400109</Sender>
<Receiver>8711200999903</Receiver>
<MessageID>000D2613F64AC021ED783C084735EC78E53</MessageID>
<CreationDateTime>2017-03-21T08:00:47Z</CreationDateTime>
</Header>
</ns:Message>
change you classes like below and it will work.
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://example.com")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://example.com", IsNullable = false)]
public partial class Message
{
private Header headerField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public Header Header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Header
{
private ulong senderField;
private ulong receiverField;
private string messageIDField;
private System.DateTime creationDateTimeField;
private decimal versionField;
/// <remarks/>
public ulong Sender
{
get
{
return this.senderField;
}
set
{
this.senderField = value;
}
}
/// <remarks/>
public ulong Receiver
{
get
{
return this.receiverField;
}
set
{
this.receiverField = value;
}
}
/// <remarks/>
public string MessageID
{
get
{
return this.messageIDField;
}
set
{
this.messageIDField = value;
}
}
/// <remarks/>
public System.DateTime CreationDateTime
{
get
{
return this.creationDateTimeField;
}
set
{
this.creationDateTimeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public decimal version
{
get
{
return this.versionField;
}
set
{
this.versionField = value;
}
}
}
OUTPUT