问题
I'm trying to deserialize a complex XML file. i have my main class structured so it gets all of the info in the first child nodes, I even have it so that i can obtain the ClientName which is two layers deep. However, anything beyond that does not seem to work. I get a List item with a count of 1 but no information is inside the list.
My OrderTaxes and OrderTransactions lists come back with a Count = 1 but all of the fields are null.
I'm positive it is a problem with my class structure and any help towards correcting this would be very appreciated.
Here is the XML:
<OrderDetail>
<MessageTypeCode>82540</MessageTypeCode>
<OrderDetailId>59339463</OrderDetailId>
<ClientInfo>
<ClientName>LenderName will appear here</ClientName>
</ClientInfo>
<OrderTaxes>
<OrderTax>
<TaxId>9202225</TaxId>
</OrderTax>
</OrderTaxes>
<OrderTransactions>
<OrderTransaction>
<LoanAmount/>
<Title>
<TitleVendors>
<TitleVendor>
<VendorInstructions>blah blah blah blah .</VendorInstructions>
<VendorServices>
<TitleVendorService>
<TitleVendorServiceId>6615159</TitleVendorServiceId>
<ServiceCode>1OWNER</ServiceCode>
<CustomVendorInstructions>blah blah blah blah blah </CustomVendorInstructions>
</TitleVendorService>
</VendorServices>
</TitleVendor>
</TitleVendors>
</Title>
</OrderTransaction>
</OrderTransactions>
</OrderDetail>
And here is the class:
namespace TSIxmlParser
{
[XmlRoot("OrderDetail")]
public class OrderData
{
[XmlElement("MessageTypeCode")]
public string MessageTypeCode { get; set; }
[XmlElement("OrderDetailId")]
public string OrderNumber { get; set; }
[XmlElement("ClientInfo")]
public List<ClientInfo> ClientInfos = new List<ClientInfo>();
[XmlArray("OrderTaxes")]
[XmlArrayItem("OrderTax")]
public List<OrderTax> OrderTaxes = new List<OrderTax>();
[XmlArray("OrderTransactions")]
[XmlArrayItem("OrderTransaction")]
public List<OrderTransaction> OrderTransactions = new List<OrderTransaction>();
}
public class ClientInfo
{
[XmlElement("ClientName")]
public string ClientName { get; set; }
}
public class OrderTax
{
[XmlElement("TaxId")]
public string TaxId { get; set; }
}
public class OrderTransaction
{
[XmlElement("LoanAmount")]
public string LoanAmount { get; set; }
[XmlArray("Title")]
[XmlArrayItem("TitleVendors")]
public List<Title> Titles { get; set; }
}
public class Title
{
[XmlArrayItem("TitleVendors")]
public List<TitleVendors> TitleVendors { get; set; }
}
public class TitleVendors
{
[XmlArray("TitleVendor")]
public List<TitleVendor> TitleVendor { get; set; }
}
public class TitleVendor
{
[XmlElement("VendorInstructions")]
public string VendorInstructions { get; set; }
[XmlArray("VendorServices")]
[XmlArrayItem("TitleVendorService")]
public List<TitleVendorService> VendorServices { get; set; }
}
public class TitleVendorService
{
[XmlElement("TitleVendorServiceId")]
public string TitleVendorServiceId { get; set; }
[XmlElement("ServiceCode")]
public string ServiceCode { get; set; }
[XmlElement("CustomVendorInstructions")]
public string CustomVendorInstructions { get; set; }
}
}
回答1:
Well, I am not sure if you wanted this (raw dump of deserialized XML):
{
MessageTypeCode: 82540,
OrderDetailId: 59339463,
ClientInfo:
{
ClientName: LenderName will appear here
},
OrderTaxes:
{
OrderTax:
{
TaxId: 9202225
}
},
OrderTransactions:
{
OrderTransaction:
{
LoanAmount: {},
Title:
{
TitleVendors:
{
TitleVendor:
{
VendorInstructions: blah blah blah blah .,
VendorServices:
{
TitleVendorService:
{
TitleVendorServiceId: 6615159,
ServiceCode: 1OWNER,
CustomVendorInstructions: blah blah blah blah blah
}
}
}
}
}
}
}
}
So basically I just used Edit -> Paste special -> Paste XML as Classes:
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class OrderDetail
{
private uint messageTypeCodeField;
private uint orderDetailIdField;
private OrderDetailClientInfo clientInfoField;
private OrderDetailOrderTaxes orderTaxesField;
private OrderDetailOrderTransactions orderTransactionsField;
/// <remarks/>
public uint MessageTypeCode
{
get
{
return this.messageTypeCodeField;
}
set
{
this.messageTypeCodeField = value;
}
}
/// <remarks/>
public uint OrderDetailId
{
get
{
return this.orderDetailIdField;
}
set
{
this.orderDetailIdField = value;
}
}
/// <remarks/>
public OrderDetailClientInfo ClientInfo
{
get
{
return this.clientInfoField;
}
set
{
this.clientInfoField = value;
}
}
/// <remarks/>
public OrderDetailOrderTaxes OrderTaxes
{
get
{
return this.orderTaxesField;
}
set
{
this.orderTaxesField = value;
}
}
/// <remarks/>
public OrderDetailOrderTransactions OrderTransactions
{
get
{
return this.orderTransactionsField;
}
set
{
this.orderTransactionsField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailClientInfo
{
private string clientNameField;
/// <remarks/>
public string ClientName
{
get
{
return this.clientNameField;
}
set
{
this.clientNameField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTaxes
{
private OrderDetailOrderTaxesOrderTax orderTaxField;
/// <remarks/>
public OrderDetailOrderTaxesOrderTax OrderTax
{
get
{
return this.orderTaxField;
}
set
{
this.orderTaxField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTaxesOrderTax
{
private uint taxIdField;
/// <remarks/>
public uint TaxId
{
get
{
return this.taxIdField;
}
set
{
this.taxIdField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactions
{
private OrderDetailOrderTransactionsOrderTransaction orderTransactionField;
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransaction OrderTransaction
{
get
{
return this.orderTransactionField;
}
set
{
this.orderTransactionField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransaction
{
private object loanAmountField;
private OrderDetailOrderTransactionsOrderTransactionTitle titleField;
/// <remarks/>
public object LoanAmount
{
get
{
return this.loanAmountField;
}
set
{
this.loanAmountField = value;
}
}
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransactionTitle Title
{
get
{
return this.titleField;
}
set
{
this.titleField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransactionTitle
{
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendors titleVendorsField;
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendors TitleVendors
{
get
{
return this.titleVendorsField;
}
set
{
this.titleVendorsField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransactionTitleTitleVendors
{
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor titleVendorField;
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor TitleVendor
{
get
{
return this.titleVendorField;
}
set
{
this.titleVendorField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor
{
private string vendorInstructionsField;
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServices vendorServicesField;
/// <remarks/>
public string VendorInstructions
{
get
{
return this.vendorInstructionsField;
}
set
{
this.vendorInstructionsField = value;
}
}
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServices VendorServices
{
get
{
return this.vendorServicesField;
}
set
{
this.vendorServicesField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServices
{
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService titleVendorServiceField;
/// <remarks/>
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService TitleVendorService
{
get
{
return this.titleVendorServiceField;
}
set
{
this.titleVendorServiceField = value;
}
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService
{
private uint titleVendorServiceIdField;
private string serviceCodeField;
private string customVendorInstructionsField;
/// <remarks/>
public uint TitleVendorServiceId
{
get
{
return this.titleVendorServiceIdField;
}
set
{
this.titleVendorServiceIdField = value;
}
}
/// <remarks/>
public string ServiceCode
{
get
{
return this.serviceCodeField;
}
set
{
this.serviceCodeField = value;
}
}
/// <remarks/>
public string CustomVendorInstructions
{
get
{
return this.customVendorInstructionsField;
}
set
{
this.customVendorInstructionsField = value;
}
}
}
All code used:
var xmlString = @
"<OrderDetail>
<MessageTypeCode>82540</MessageTypeCode>
<OrderDetailId>59339463</OrderDetailId>
<ClientInfo>
<ClientName>LenderName will appear here</ClientName>
</ClientInfo>
<OrderTaxes>
<OrderTax>
<TaxId>9202225</TaxId>
</OrderTax>
</OrderTaxes>
<OrderTransactions>
<OrderTransaction>
<LoanAmount/>
<Title>
<TitleVendors>
<TitleVendor>
<VendorInstructions>blah blah blah blah .</VendorInstructions>
<VendorServices>
<TitleVendorService>
<TitleVendorServiceId>6615159</TitleVendorServiceId>
<ServiceCode>1OWNER</ServiceCode>
<CustomVendorInstructions>blah blah blah blah blah </CustomVendorInstructions>
</TitleVendorService>
</VendorServices>
</TitleVendor>
</TitleVendors>
</Title>
</OrderTransaction>
</OrderTransactions>
</OrderDetail>";
var xml = new OrderDetail();
System.Xml.Serialization.XmlSerializer serializer = new
System.Xml.Serialization.XmlSerializer(typeof(OrderDetail));
using(XmlReader reader = XmlReader.Create(new StringReader(xmlString))) {
xml = (OrderDetail) serializer.Deserialize(reader);
}
var xmlDump = xml.Dump();
回答2:
The .NET SDK provides a great tool for this. The XML Schedma Definition Tool (csd.exe).
More Info: http://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx
I ran through an example using your XML to show you have it works.
- First I saved your XML to my desktop to a file named 'sample.xml'
- I opened up the VS 2012 Command Prompt as Administrator.
In the Command Prompt, I navigated to the directory where the SDK is installed. For me its installed here (might be different with various OS or VS versions):
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 ToolsI ran the following command to create an XSD for your XML. (Expect sample.xsd to appear on the desktop)
xsd "c:\users\glenn\desktop\sample.xml" /outputdir:"c:\users\glenn\desktop"I ran the following command to create a CSharp file from the resultant XSD file.
xsd "c:\users\glenn\desktop\sample.xsd" /classes /outputdir:"c:\users\glenn\desktop"
Excluding the comments, this is the CSharp file that is custom generated for your XML schema. There are additional options to set the namespace and typename. Please review the article above for that detail.
using System.Xml.Serialization;
[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 OrderDetail {
private string messageTypeCodeField;
private string orderDetailIdField;
private OrderDetailClientInfo[] clientInfoField;
private OrderDetailOrderTaxesOrderTax[][] orderTaxesField;
private OrderDetailOrderTransactionsOrderTransaction[][] orderTransactionsField;
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string MessageTypeCode {
get {
return this.messageTypeCodeField;
}
set {
this.messageTypeCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string OrderDetailId {
get {
return this.orderDetailIdField;
}
set {
this.orderDetailIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ClientInfo", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public OrderDetailClientInfo[] ClientInfo {
get {
return this.clientInfoField;
}
set {
this.clientInfoField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("OrderTax", typeof(OrderDetailOrderTaxesOrderTax), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public OrderDetailOrderTaxesOrderTax[][] OrderTaxes {
get {
return this.orderTaxesField;
}
set {
this.orderTaxesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("OrderTransaction", typeof(OrderDetailOrderTransactionsOrderTransaction), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public OrderDetailOrderTransactionsOrderTransaction[][] OrderTransactions {
get {
return this.orderTransactionsField;
}
set {
this.orderTransactionsField = 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 OrderDetailClientInfo {
private string clientNameField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string ClientName {
get {
return this.clientNameField;
}
set {
this.clientNameField = 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 OrderDetailOrderTaxesOrderTax {
private string taxIdField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string TaxId {
get {
return this.taxIdField;
}
set {
this.taxIdField = 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 OrderDetailOrderTransactionsOrderTransaction {
private string loanAmountField;
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor[][][] titleField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string LoanAmount {
get {
return this.loanAmountField;
}
set {
this.loanAmountField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("TitleVendors", typeof(OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor[]), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
[System.Xml.Serialization.XmlArrayItemAttribute("TitleVendor", typeof(OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false, NestingLevel=1)]
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor[][][] Title {
get {
return this.titleField;
}
set {
this.titleField = 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 OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendor {
private string vendorInstructionsField;
private OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService[][] vendorServicesField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string VendorInstructions {
get {
return this.vendorInstructionsField;
}
set {
this.vendorInstructionsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlArrayAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
[System.Xml.Serialization.XmlArrayItemAttribute("TitleVendorService", typeof(OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService), Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=false)]
public OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService[][] VendorServices {
get {
return this.vendorServicesField;
}
set {
this.vendorServicesField = 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 OrderDetailOrderTransactionsOrderTransactionTitleTitleVendorsTitleVendorVendorServicesTitleVendorService {
private string titleVendorServiceIdField;
private string serviceCodeField;
private string customVendorInstructionsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string TitleVendorServiceId {
get {
return this.titleVendorServiceIdField;
}
set {
this.titleVendorServiceIdField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string ServiceCode {
get {
return this.serviceCodeField;
}
set {
this.serviceCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string CustomVendorInstructions {
get {
return this.customVendorInstructionsField;
}
set {
this.customVendorInstructionsField = 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 NewDataSet {
private OrderDetail[] itemsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("OrderDetail")]
public OrderDetail[] Items {
get {
return this.itemsField;
}
set {
this.itemsField = value;
}
}
}
Hope this helps!
回答3:
Try using XmlArray and XmlArrayItem on the corresponding properties.
[XmlArray("OrderTaxes")]
[XmlArrayItem("OrderTax")]
public List<OrderTax> OrderTaxes = new List<OrderTax>();
and
[XmlArray("OrderTransactions")]
[XmlArrayItem("OrderTransaction")]
public List<OrderTransaction> OrderTransactions = new List<OrderTransaction>();
This way the serializer will know that these are to be treated as collections and will know how to look for a specific item.
Besides these two I would say that wherever you are defining a list of elements you should use this approach. TitleVendors most likely will need something similar.
回答4:
Since this is still open I thought I'd throw in a quick answer, suitable for XmlSerializer. In making the classes, I assumed a pattern resembling this:
<Foo>
<Bars>
<Bar>
Means that class "Foo" contains a list of instances of class "Bar". A pattern like this:
<Foo>
<Bar>
Means that class "Foo" contains a single reference to an instance of class "Bar". Thus you should only have a single "Title" inside your "OrderTransaction", not a list of them:
public class OrderDetail
{
public string MessageTypeCode { get; set; }
public string OrderDetailId { get; set; }
public ClientInfo ClientInfo { get; set; }
public List<OrderTax> OrderTaxes { get; set; }
public List<OrderTransaction> OrderTransactions { get; set; }
}
public class OrderTransaction
{
public string LoanAmount { get; set; }
public Title Title { get; set; }
}
public class Title
{
public List<TitleVendor> TitleVendors { get; set; }
}
public class TitleVendor
{
public string VendorInstructions { get; set; }
public List<TitleVendorService> VendorServices { get; set; }
}
public class TitleVendorService
{
public string TitleVendorServiceId { get; set; }
public string ServiceCode { get; set; }
public string CustomVendorInstructions { get; set; }
}
public class ClientInfo
{
public string ClientName { get; set; }
}
public class OrderTax
{
public string TaxId { get; set; }
}
None of the XML-related decorations are actually required. XmlElement and XmlArray are only needed if you want to override XmlSerializer's default choices, for instance to rename the element or to handle arrays with polymorphic elements. You can put them if you want to for clarity, or to protect against renaming the property down the road, but I didn't for simplicity.
Here's the test setup. I create an instance of "OrderDetail" from your string, then re-serialize it to XML, then save the original and rewritten XML as files and diff them in a command prompt window:
public static class TestOrderDetail
{
public static string TestString =
@"<OrderDetail>
<MessageTypeCode>82540</MessageTypeCode>
<OrderDetailId>59339463</OrderDetailId>
<ClientInfo>
<ClientName>LenderName will appear here</ClientName>
</ClientInfo>
<OrderTaxes>
<OrderTax>
<TaxId>9202225</TaxId>
</OrderTax>
</OrderTaxes>
<OrderTransactions>
<OrderTransaction>
<LoanAmount/>
<Title>
<TitleVendors>
<TitleVendor>
<VendorInstructions>blah blah blah blah .</VendorInstructions>
<VendorServices>
<TitleVendorService>
<TitleVendorServiceId>6615159</TitleVendorServiceId>
<ServiceCode>1OWNER</ServiceCode>
<CustomVendorInstructions>blah blah blah blah blah </CustomVendorInstructions>
</TitleVendorService>
</VendorServices>
</TitleVendor>
</TitleVendors>
</Title>
</OrderTransaction>
</OrderTransactions>
</OrderDetail>";
public static void Test()
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(OrderDetail));
OrderDetail orderDetail = (OrderDetail)serializer.Deserialize(new StringReader(TestString));
string newTestString = TestWrite(serializer, orderDetail);
var guid = DateTime.Now.Ticks;
var path = Path.GetTempPath();
var file1 = path + Path.DirectorySeparatorChar + "OldOrderDetail_" + guid.ToString() + ".xml";
var file2 = path + Path.DirectorySeparatorChar + "NewOrderDetail_" + guid.ToString() + ".xml";
File.WriteAllText(file1, TestString);
File.WriteAllText(file2, newTestString);
}
catch (Exception e)
{
Debug.Assert(false, e.ToString());
}
}
private static string TestWrite(XmlSerializer serializer, OrderDetail orderDetail)
{
using (var textWriter = new StringWriter())
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true; // For testing purposes, disable the xml version and encoding declarations.
settings.Indent = true;
settings.IndentChars = " "; // The indentation used in the test string.
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", ""); // For testing purposes, disable the xmlns:xsi and xmlns:xsd lines, which were not in the test string.
serializer.Serialize(xmlWriter, orderDetail, ns);
}
return textWriter.ToString();
}
}
}
Here's the result of diffing the old and new XML files:
diff OldOrderDetail_635420738451748332.xml NewOrderDetail_635420738451748332.xml
14c14
< <LoanAmount/>
---
> <LoanAmount />
Other than inserting an extra space for formatting in the empty "LoanAmount" element, there's no difference.
回答5:
Btw XmlSerializer and DataContractSerializer are complete different. According your sample you need to use XmlSeralizer (not DataContractSerializer).
回答6:
This is what I have so far. This code produces the following structure:
-OrderTransactions (Count = 1)
- Loan Amount = ""
- Titles (Count = 1)
-TitleVendors (Count = 1)
- VendorInstructions = null
- VendorServices (Count = 0)
It seems to be seeing the nodes inside TitleVendors, but it doesn't grab the information.
<OrderTransactions>
<OrderTransaction>
<LoanAmount /> --this may be NULL - this should not cause the message to fail.
<Title>
<TitleVendors>
<TitleVendor>
<VendorInstructions>Endorsements required: EPA, COMP, PUD. **Attention Abstractor: THIS IS A VA LOAN** **Attention Abstractor: If a PRIVATE ROAD EASEMENT exists, please provide any information and copies along with the abstract.</VendorInstructions>
<VendorServices>
<TitleVendorService>
<TitleVendorServiceId>6615159</TitleVendorServiceId>
<ServiceCode>1OWNER</ServiceCode>
<CustomVendorInstructions><p><b>Copies of recital page, legal description and signature pages of all open mortgages must be provided including copies of the legal description and any riders.<br /> <br /> Copies of assignments must be provided for open liens.<br /> <br /> If the property is registered land a copy of the certificate of title must accompany the search</CustomVendorInstructions>
</TitleVendorService>
</VendorServices>
</TitleVendor>
</TitleVendors>
</Title>
</OrderTransaction>
</OrderTransactions>
[XmlArray("OrderTransactions")]
[XmlArrayItem("OrderTransaction")]
public List<OrderTransaction> OrderTransactions = new List<OrderTransaction>();
public class OrderTransaction
{
[XmlElement("LoanAmount")]
[DataMember]
public string LoanAmount { get; set; }
[XmlArray("Title")]
[XmlArrayItem("TitleVendors")]
public List<Title> Titles = new List<Title>();
public class Title
{
[XmlArray("TitleVendor")]
[XmlArrayItem("VendorInstructions")]
//[XmlArrayItem("VendorServices")]
public List<TitleVendor> TitleVendors = new List<TitleVendor>();
public class TitleVendor
{
[XmlElement("VendorInstructions")]
[DataMember]
public string VendorInstructions { get; set; }
[XmlArray("VendorServices")]
[XmlArrayItem("TitleVendorService")]
public List<VendorService> VendorServices = new List<VendorService>();
public class VendorService
{
public List<TitleVendorService> TitleVendorServices = new List<TitleVendorService>();
public class TitleVendorService
{
[XmlElement("TitleVendorServiceId")]
[DataMember]
public string TitleVendorServiceId { get; set; }
[XmlElement("ServiceCode")]
[DataMember]
public string ServiceCode { get; set; }
[XmlElement("CustomVendorInstructions")]
[DataMember]
public string CustomVendorInstructions { get; set; }
}
}
}
}
}
来源:https://stackoverflow.com/questions/24921577/complex-xml-deserialization