I'm trying to parse a xml file in an object
This is my xml file named Changelog.xml
<?xml version="1.0" encoding="utf-8" ?>
<Changelog>
<Releases>
<Release>
<Version>1507</Version>
<Date>22-11-2013</Date>
<Changes>
<Change>Change1</Change>
<Change>Change2</Change>
<Change>Change3</Change>
<Change>Change4</Change>
</Changes>
</Release>
<Release>
<Version>1506</Version>
<Date>20-11-2013</Date>
<Changes>
<Change>Change1</Change>
</Changes>
</Release>
</Releases>
</Changelog>
This is my Changelog object I want to cast the xml to
[XmlRoot()]
public class Changelog
{
private List<Release> releases;
public List<Release> Releases
{
get { return releases; }
set { releases = value; }
}
}
public class Release
{
private string version;
private string date;
private List<ChangeItem> changes;
[XmlElement]
public string Version
{
get { return version; }
set { version = value; }
}
[XmlElement]
public string Date
{
get { return date; }
set { date = value; }
}
[XmlElement]
public List<ChangeItem> Changes
{
get { return changes; }
set { changes = value; }
}
}
public class ChangeItem
{
private string change;
[XmlElement]
public string Change
{
get { return change; }
set { change = value; }
}
}
Here I read the file
XmlSerializer serializer = new XmlSerializer(typeof(Changelog));
Changelog changelog = (Changelog)serializer.Deserialize(new StreamReader(#"changelog.xml"));
Releases = changelog.Releases;
foreach (Release release in Releases)
{
string version = release.Version;
string date = release.Date;
List<ChangeItem> changes = release.Changes; // Has only 1 item
}
The problem is that there is only 1 object in the Changes list, altough I expect 4 for the 1507 release.
What am I doing wrong?
You have ChangeItem.Change property decorated with an XmlElement attribute. This means it becomes another element.
Thus the xml would need to look different.
To make it work, mark the property with the [XmlText] attribute.
Also, your Release.Changes needed to be decorated with a XmlArray and a XmlArrayItem attribute.
[XmlRoot]
public class Changelog
{
private List releases;
public List Releases
{
get { return releases; }
set { releases = value; }
}
}
public class Release
{
private string version;
private string date;
private List changes;
[XmlElement]
public string Version
{
get { return version; }
set { version = value; }
}
[XmlElement]
public string Date
{
get { return date; }
set { date = value; }
}
[XmlArray("Changes")]
[XmlArrayItem("Change")]
public List Changes
{
get { return changes; }
set { changes = value; }
}
}
public class ChangeItem
{
private string change;
[XmlText]
public string Change
{
get { return change; }
set { change = value; }
}
}
I marked in bold what my changes were.
change
[XmlElement]
public List<ChangeItem> Changes
{
get { return changes; }
set { changes = value; }
}
to
[XmlArray("Changes")]
public List<ChangeItem> Changes
{
get { return changes; }
set { changes = value; }
}
Related
I have a Dictionary with Key-Value pair where Value is a complex Object.
Becaouse of a speed I have used AsParalle().
Problem that occures is that in some of my return objects are placed multiple results of other Key-Value pair.
For examle:
ResutDict has multiple Key-Value pairs.
public IDictionary<string, IOutboundResult> ResultDict
{
get { return m_ResultDict; }
set { m_ResultDict = value; }
}
ResultDict.AsParallel()
.WithDegreeOfParallelism(amountOfThreads)
.ForAll(kvp => { DO YOUR THING AND RETURN OBJECT S_Out}
All of them should return one Object. That later will be serialized into XML.
public class S_Out : ISerializable
{
private List<details> detailField;
[System.Xml.Serialization.XmlElement("details")]
public List<details> details
{
get { return detailField; }
set { detailField = value; }
}
}
public class details
{
private string idField;
private string countryField;
private string town_cityField;
private string postcodeField;
private List<extract> extractField;
public string id
{
get { return idField; }
set { idField = value; }
}
public string country
{
get { return countryField; }
set { countryField = value; }
}
public string town_city
{
get { return town_cityField; }
set { town_cityField = value; }
}
public string postcode
{
get { return postcodeField; }
set { postcodeField = value; }
}
[XmlElement("extract")]
public List<extract> extract
{
get { return extractField; }
set { extractField = value; }
}
}
This list of details is there only for some other cases, but in this particular case should contain only one detail.
During Parallel different Threads write in there so in some files I have no detail object, and in some of them whole list of details.
It should be one detail for one xml file.
Have anyone Idea why is this happening?
I'm using DataContractJsonSerializer to deserialize JSON from a Webservice.
[{"id":2947,"type":"PdfDocument","name":"test.pdf"},
{"id":2945,"type":"ImageDocument","name":"test.jpg", "color": "green"}]
Based on their type, JSON entities can have different properties (for example a color). Currently i use a single model Document for deserialization and PagedCollectionViews to filter what i need to show in the UI.
public class Document : EntityBase
{
private string name;
private string type;
private string color;
public Document()
{
}
[DataMember(Name = "name")]
public string Name
{
get
{
return this.name;
}
set
{
if (this.name != value)
{
this.name = value;
this.OnPropertyChanged("Name");
}
}
}
[DataMember(Name = "type")]
public string Type
{
get
{
return this.type;
}
set
{
if (this.type != value)
{
this.type = value;
this.OnPropertyChanged("Type");
}
}
}
[DataMember(Name = "color")]
public string Color
{
get
{
return this.color;
}
set
{
if (this.color != value)
{
this.color= value;
this.OnPropertyChanged("Color");
}
}
}
}
public class DocumentsViewModel : ViewModelBase
{
public ObservableCollection<Document> Documents { get; set; }
public PagedCollectionView ImageDocuments;
public PrintProjectDetailsViewModel()
{
this.Documents = new ObservableCollection<Document>();
this.ImageDocuments = new PagedCollectionView(Documents);
this.ImageDocuments.Filter = (o) => ((Document)o).Type == "ImageDocument";
}
}
However, that feels "smelly" to me. Is it possible to automatically deserialize to a subclass of Document depending of the JSON value of type?
Let me take it straight. Is it possible to not serialize an XMLArray elements if it null? As in following XML "Details" is used. Is it possible to not to have it in XML if it is null. Please check my code and will appreciate some thoughts on it.
<agr:InvoiceNo>99999</agr:InvoiceNo>
<agr:Header>
<agr:LineNo>1</agr:LineNo>
<agrlib:InvoiceDate>2013-02-13</agrlib:InvoiceDate>
<agrlib:DueDate>2013-03-15</agrlib:DueDate>
<agr:ArchiveRef>27624642</agr:ArchiveRef>
<agr:ArchivePath>Images\20130315\10_00000030_00000</agr:ArchivePath>
<agr:Currency>SEK</agr:Currency>
<agr:Seller>
<agrlib:CompRegNo>999999</agrlib:CompRegNo>
</agr:Seller>
<agr:Buyer>
<agrlib:CompanyCode>10</agrlib:CompanyCode>
<agr:Accountable />
</agr:Buyer>
<agr:PaymentInfo>
<agr:AccountNumber>99999</agr:AccountNumber>
<agrlib:BacsId />
</agr:PaymentInfo>
<agrlib:ReferenceCode>
<agrlib:Code>AA</agrlib:Code>
<agrlib:Value>AAAA</agrlib:Value>
<agrlib:Description />
</agrlib:ReferenceCode>
</agr:Header>
<Details /> <!-- this one -->
<agr:Summary>
<agr:TotalTax>170.36</agr:TotalTax>
<agr:TotalInclTax>1590.00</agr:TotalInclTax>
</agr:Summary>
</agr:Invoice>
[Serializable]
public class Invoice
{
private Header _header = new Header();
private Summary _summary = new Summary();
private List<Detail> _details = new List<Detail>();
[XmlElement("InvoiceNo")]
public string InvoiceNo { get; set; }
[XmlElement("Header")]
public Header Header
{
get { return _header; }
set { _header = value; }
}
[XmlArray("Details"), XmlArrayItem("Detail", typeof(Detail), IsNullable=false)]
public List<Detail> Details
{
get { return _details; }
set { _details = value; }
}
[XmlElement("Summary")]
public Summary Summary
{
get { return _summary; }
set { _summary = value; }
}
}
[XmlType(TypeName = "Detail"), Serializable]
public class Detail
{
private Product _product = new Product();
static CultureInfo ci = CultureInfo.InvariantCulture;
private float _lineTotExclTax = 0;
[XmlElement("LineNo")]
public int LineNo { get; set; }
[XmlIgnore]
public float LineTotExclTax
{
get { return _lineTotExclTax; }
set { _lineTotExclTax = value; }
}
[XmlElement("LineTotExclTax")]
public string CustomLineTotExclTax
{
get { return LineTotExclTax.ToString("#0.00", ci); }
set { float.TryParse(value, NumberStyles.Float, ci, out _lineTotExclTax); }
}
[XmlElement("Products")]
public Product Product
{
get { return _product; }
set { _product = value; }
}
}
If the list truly is null it is ignored. To get the output you show, it must be an empty non-null list, probably due to the field-initializer:
private List<Detail> _details = new List<Detail>();
If you can't make it null, then consider ShouldSerialize*:
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeDetails()
{
return _details != null && _details.Count != 0;
}
This defines a custom rule for when the property Details should / should not be serialized.
I've got class in WCF. Inside this class - there are 2 classes, 1 interface and several variables. It adds as service reference without errors.
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class XmlService
{
private string filename;
private XmlTextReader xmlreader;
List<IWeather> returner=new List<IWeather>();
[OperationContract]
public void DoWork()
{
// Add your operation implementation here
return;
}
interface IWeather
{
string GetCondition { get; set; }
DateTime GetDate { get; set; }
}
public class Current_Weather:IWeather
{
private string condition, humidity, wind_condition;
private int temp_f, temp_c;
private DateTime day;
public string GetCondition
{
get { return condition; }
set { condition = value; }
}
public string GetHumidity
{
get { return humidity; }
set { humidity = value; }
}
public string GetWindCondition
{
get { return wind_condition; }
set { wind_condition = value; }
}
public int TEMP_F
{
get { return temp_f; }
set { temp_f = value; }
}
public int TEMP_C
{
get { return temp_c; }
set { temp_c = value; }
}
public DateTime GetDate
{
get { return day; }
set { day = value; }
}
}
public class Forecast_Weather:IWeather
{
public string condition;
public int lowT, highT;
public DateTime day;
public string GetCondition
{
get { return condition; }
set { condition = value; }
}
public int GetLowT
{
get { return lowT; }
set { lowT = value; }
}
public int HighT
{
get { return highT; }
set { highT = value; }
}
public DateTime GetDate
{
get { return day; }
set { day = value; }
}
}
}
Should I add contracts to variables,interface IWeather, for inner classes and its methods and variables?
If you want them serialzied and visible on the client they need to be marked with contract attributes.
Internal classes aren't really a good practice, instead put all your operations in one interface marked up as a service contract, then all your data contracts in their own class libraries so you can reference that assemply frmo your client. This facilitates writing your own proxies and other good habits.
Your internal classes will not be exposed to callers of your service, since your service doesn't use them either as parameters or as return values.
I have a XML document with a node like this.
<channel id="3102" platform = "1" activation="30/11/2010" desactivation="">
And I want to deserialize it using DataContract and Data Member attributes, which are working well with its properties but are not deserializing the attributes.
[DataContract(Namespace="")]
[XmlSerializerFormat]
public abstract class Channel
{
#region variables privadas
[DataContract(Namespace="")]
[XmlSerializerFormat]
//[KnownType(typeof(AudioChannel))]
//[KnownType(typeof(VideoChannel))]
public abstract class Channel
{
#region variables privadas
private DateTime _desactivation;
private DateTime _activation;
private int _platform;
private int _id;
....
#endregion
#region Propiedades públicas
[DataMember]
[XmlAttribute(AttributeName="desactivation")]
public DateTime Desactivation
{
get { return _desactivation; }
set { _desactivation = value; }
}
[DataMember]
[XmlAttribute(AttributeName="activation")]
public DateTime Activation
{
get { return _activation; }
set { _activation = value; }
}
[DataMember]
[XmlAttribute(AttributeName="platform")]
public int Platform
{
get { return _platform; }
set { _platform = value; }
}
#endregion
#region Propiedades públicas
[DataMember]
[XmlAttribute(AttributeName="desactivation")]
public DateTime Desactivation
{
get { return _desactivation; }
set { _desactivation = value; }
}
[DataMember]
[XmlAttribute(AttributeName="activation")]
public DateTime Activation
{
get { return _activation; }
set { _activation = value; }
}
[DataMember]
[XmlAttribute(AttributeName="platform")]
public int Platform
{
get { return _platform; }
set { _platform = value; }
} ...
My properties associated to these attributes are not filled, what I'm doing wrong?
Thanks in advance for any help provided.
Repeated question. How can you control .NET DataContract serialization so it uses XML attributes instead of elements? You can't do that with a DataContractSerializer, but you should achieve what you ask for using the XmlSerializer.