How to write/set sub-node with multiple cdata xml c# - c#

I try to produce XML like below
<?xml version="1.0" encoding="UTF-8"?>
<movie>
<title><![CDATA[Con Air]]></title>
<plot><![CDATA[When the government puts all its rotten criminal eggs in one airborne basket, it's asking for trouble. Before you can say, "Pass the barf bag," the crooks control the plane, led by creepy Cyrus "The Virus" Grissom. Watching his every move is the just-released Cameron Poe, who'd rather reunite with his family. The action climaxes with an incredible crash sequence in Las Vegas.]]></plot>
<tagline><![CDATA[They were deadly on the ground; Now they have wings]]></tagline>
<year>1997</year>
<id>tt0118880</id>
<rating>65</rating>
<votes>93</votes>
<budget>75000000</budget>
<revenue>224012234</revenue>
<company><![CDATA[Touchstone Pictures]]></company>
<genre>
<name><![CDATA[Action]]></name>
<name><![CDATA[Adventure]]></name>
<name><![CDATA[Thriller]]></name>
</genre>
</movie>
I use C# XmlDocument to generate the XML File using serializable class below
[Serializable]
public class movie
{
public movie()
{
this.genre = new Genre();
}
[XmlIgnore]
public string title { get; set; }
[XmlElement("title")]
public XmlCDataSection titleCDATA
{
get { return new XmlDocument().CreateCDataSection(title); }
set { title = value.Value; }
}
[XmlIgnore]
public string plot { get; set; }
[XmlElement("plot")]
public XmlCDataSection plotCDATA
{
get { return new XmlDocument().CreateCDataSection(plot); }
set { plot = value.Value; }
}
[XmlIgnore]
public string tagline { get; set; }
[XmlElement("tagline")]
public XmlCDataSection taglineCDATA
{
get { return new XmlDocument().CreateCDataSection(tagline); }
set { tagline = value.Value; }
}
public int year { get; set; }
public string id { get; set; }
public int rating { get; set; }
public int votes { get; set; }
public long budget { get; set; }
public long revenue { get; set; }
[XmlIgnore]
public string company { get; set; }
[XmlElement("company")]
public XmlCDataSection companyCDATA
{
get { return new XmlDocument().CreateCDataSection(company); }
set { company = value.Value; }
}
[XmlElement("genre")]
public Genre genre { get; set; }
}
public class Genre
{
public Genre()
{
}
public string[] name { get; set; }
}
But the output not as expected like below
<?xml version="1.0" encoding="utf-16"?>
<movie>
<title><![CDATA[Monster House]]></title>
<plot><![CDATA[Monsters under the bed are scary enough, but what happens when an entire house is out to get you? Three teens aim to find out when they go up against a decrepit neighboring home and unlock its frightening secrets.]]></plot>
<tagline><![CDATA[The House is . . . ALIVE!]]></tagline>
<year>2006</year>
<id>tt0385880</id>
<rating>57</rating>
<votes>74</votes>
<budget>0</budget>
<revenue>0</revenue>
<company><![CDATA[Sony Pictures Entertainment]]></company>
<genre>
<name>
<string>Adventure</string>
<string>Animation</string>
<string>Comedy</string>
<string>Fantasy</string>
<string>Mystery</string>
<string>Science Fiction</string>
<string>Family</string>
</name>
</genre>
</movie>
How can I create sub-node xml like the genre sub-node in the first example?

I think your issue with element names called "string" instead of "name" should be solved by using proper annotation as covered in Controlling XML Serialization Using Attributes .
You'll have to modify you class a bit (and I'm not sure you can get CDATA for names, but it should be fine):
public class Movie
{
....
[XmlArray("genre")]
[XmlArrayItem("Name")]
public string[] Genre { get; set; }
}

Related

XML Deserializing returns "some" null values

Here's my XML:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<p>this is an "event"</p>
</Description>
<Speakers>speaker1 LLC<br />speaker2<br />Jspeaker3</Speakers>
<Time>5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception</Time>
<Where></Where>
<RegistrationInfo>Please contact events#events.com to register for this event.</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content "can you display it."</content_teaser>
<content_text>text of the vent "more text" a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
<Event>.... Other events </Event>
<Events>
and here's are my classes:
public class Serializable_Events
{
[XmlElement("Event")]
public List<Serializable_Event> EventList = new List<Serializable_Event>();
}
public class Serializable_Event
{
[XmlElement("content_id")]
public string content_id { get; set; }
[XmlElement("content_title")]
public string content_title { get; set; }
[XmlElement("content_html")]
public Serializable_Event_ContentHTML ContentHTML { get; set; }
[XmlText]
public string content_teaser { get; set; }
[XmlElement("content_text")]
public string content_text { get; set; }
}
public class Serializable_Event_ContentHTML
{
[XmlElement("Date")]
public string Date { get; set; }
[XmlElement("EventType")]
public string EventType { get; set; }
[XmlElement("Description")]
public string Description { get; set; }
[XmlElement("Speakers")]
public string Speakers { get; set; }
[XmlElement("Time")]
public string Time { get; set; }
[XmlElement("Where")]
public string Where { get; set; }
[XmlElement("RegistrationInfo")]
public string RegistrationInfo { get; set; }
[XmlElement("Registration")]
public bool Registration { get; set; }
//ignored html tags
[XmlIgnore]
public string p { get; set; }
[XmlIgnore]
public string br { get; set; }
[XmlIgnore]
public string a { get; set; }
}
Implementation:
XmlSerializer ser = new XmlSerializer(typeof(Serializable_Events));
var data = (Serializable_Events)ser.Deserialize(new StreamReader(#"events.xml"));
My problem is that some attributes are null and some are not (see the screenshot)
The ones that are null, like <Description> are due to malformed
XML.
You are storing HMTL directly in XML with text all over the place, and the serializer is not expecting that; further you are telling the serializer to ignore HTML tags using XmlIgnore which is intended for XML tags with properly formed XML. That's a wrong use of XmlIgnore
All XML which contains non-XML mark-up should be wrapped in CDATA sections; this will solve your problem. Further, you can remove all of the XmlIgnore code as well since it's not needed.
Your XML should look like this:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<![CDATA[<p>this is an ""event""</p>]]>
</Description>
<Speakers>
<![CDATA[speaker1 LLC<br />speaker2<br />Jspeaker3]]>
</Speakers>
<Time>
<![CDATA[5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception]]>
</Time>
<Where></Where>
<RegistrationInfo>
<![CDATA[Please contact <a href='mailto:events#events.com'>events#events.com</a> to register for this event.]]>
</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content 'can you display it.'</content_teaser>
<content_text>text of the vent 'more text' a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
</Events>"

Xml Serialization for list Property doesn't work when one item in the list

<TotalRecords ItineraryCount='1' >
<Recs ItineraryNumber="1" >
<Amount>516.6</Amount>
<TravelTime>940</TravelTime>
<FSegment>
<OutProperty>
<Segment No="1">
<Name>Ronald</Name>
<City>London</City>
<Country>United Kingdom</Country>
</Segment>
<Segment No="2">
<Name>Richard</Name>
<City>
London
</City>
<Country>United Kingdom</Country>
</Segment>
</OutProperty>
</FSegment>
</Recs>
</TotalRecords >
I am serializing xml to object of TotalRecords Class. It works fine when there are more than one segment in the OutProperty but in case of one segment it doesn't serialize into list property.
I have also tried with [XmlArray("")] and [XMlArrayItem("")] but it doesn't work. Anyone have idea?
public class TotalRecords
{
public Recs recs { get; set; }
public string ItineraryCount { get; set; }
}
public partial class Recs
{
public string amountField { get; set; }
public string travelTimeField { get; set; }
public FSegment fSegmentField { get; set; }
public string itineraryNumberField { get; set; }
}
public class FSegment
{
public List<Segment> OutProperty {get;set;}
}
public class Segment
{
public string nameField { get; set; }
public string cityField { get; set; }
public string countryField { get; set; }
}
Try to use the following for your Classes and their Properties:
[DataContract]
public class Contact
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Hacking like this helps in many cases, perhaps in your too (converting List to array):
public class FSegment
{
[XmlIgnore]
public List<Segment> OutProperty {get;set;}
[XmlArray("OutProperty");
public Segment[] _OutProperty
{
get { return OutProperty.ToArray(); }
set { OutProperty = new List<Segment>(value); }
}
}
I am not exactly sure how your provided class definition worked previously without any XML attribute/element definitions since your variable names are not the same as the XML identifiers, meaning that the serialization wouldn't populate the properties that it couldn't find a name for.
Nether the less, the main issue here is that you are trying to put a list into a normal property.
From the XML provided, OutProperty is a single sub element of FSegment and Segment is an array of sub elements of OutProperty, but in your provided code, you tried to make Segment an array sub element of FSegment.
The correct structure of the class definition should be as follows (also including the XML definitions)
[System.Xml.Serialization.XmlRoot(ElementName="TotalRecords")]
public class TotalRecords
{
[System.Xml.Serialization.XmlElement(ElementName="Recs")]
public Recs recs { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryCount")]
public string ItineraryCount { get; set; }
}
public partial class Recs
{
[System.Xml.Serialization.XmlElement(ElementName = "Amount")]
public string amountField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "TravelTime")]
public string travelTimeField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "FSegment")]
public FSegment fSegmentField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "ItineraryNumber")]
public string itineraryNumberField { get; set; }
}
public class FSegment
{
[System.Xml.Serialization.XmlElement(ElementName = "OutProperty")]
public SegmentList OutProperty { get; set; }
}
public class SegmentList
{
[System.Xml.Serialization.XmlElement(ElementName = "Segment")]
public List<Segment> segmentField { get; set; }
}
public class Segment
{
[System.Xml.Serialization.XmlElement(ElementName = "Name")]
public string nameField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "City")]
public string cityField { get; set; }
[System.Xml.Serialization.XmlElement(ElementName = "Country")]
public string countryField { get; set; }
[System.Xml.Serialization.XmlAttribute(AttributeName = "No")]
public int segmentNoField { get; set; }
}
Please note that in the above structure, Segment is a list object under the OutProperty object, which resides under the FSegment object.
Using this class structure to load your XML produces the (assumed) correct data in the created objects.
Using the XML definitions allows you to decouple the actual names of class properties from what they are called in the XML data. This allows you to changes the one or the other without affecting the other one, which is useful when you don't control the creation of the XML data.
If you don't want all the XML definitions in your code, change the names of the classes so that you can name your properties the same as what they are called in the XML file. That will allow you couple everything directly

Xml Deserialize returms null values but xml has values

I saw few topics but no one looks like my problem.
Here is my class:
namespace Framework.Cielo.Models
{
[XmlRoot("transacao", Namespace = "http://ecommerce.cbmp.com.br")]
public class TransactionResponse
{
[XmlAttribute("id")]
public string ID { get; set; }
[XmlAttribute("versao")]
public string Version { get; set; }
[XmlElement("tid")]
public string tid { get; set; }
[XmlElement("pan")]
public string pan { get; set; }
[XmlElement("dados-pedido")]
public EstablishmentOrder Order { get; set; }
[XmlElement("forma-pagamento")]
public PaymentMethod PaymentMethod { get; set; }
[XmlElement("status")]
public TransactionStatusEnum Status { get; set; }
[XmlElement("url-retorno")]
public string ReturnUrl { get; set; }
[XmlElement("autenticacao")]
public Authentication Authentication { get; set; }
}
}
and here is the authentication class
namespace Framework.Cielo.Models
{
[XmlRoot("autenticacao")]
public class Authentication
{
[XmlElement("codigo")]
public int Code { get; set; }
[XmlElement("mensagem")]
public string Message { get; set; }
[XmlIgnore]
public DateTime Date { get; set; }
[XmlElement("data-hora")]
public string FormattedDate
{
get
{
return Date.ToString("yyyy-MM-ddTHH:mm:ss");
}
set
{
DateTime kdc = DateTime.MinValue;
DateTime.TryParse(value, out kdc);
Date = kdc;
}
}
[XmlElement("valor")]
public int Value { get; set; }
[XmlElement("lr")]
public int SecurityLevel { get; set; }
[XmlElement("arp")]
public object arp { get; set; }
[XmlElement("nsu")]
public object nsu { get; set; }
}
}
Here is how I deserialize:
string serializado = File.ReadAllText("req.xml");
var stringReader = new System.IO.StringReader(serializado);
var serializer = new XmlSerializer(typeof(TransactionResponse));
TransactionResponse preAuthResponse = serializer.Deserialize(stringReader) as TransactionResponse;
and here is my XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<transacao versao="1.3.0" id="100" xmlns="http://ecommerce.cbmp.com.br">
<tid>10069930690A16DF1001</tid>
<pan>b1SQ6jpKCDt3n9C0dgD/ZkPQ1Bh+7aJESqr/CwP64P0=</pan>
<dados-pedido>
<numero>100</numero>
<valor>29900</valor>
<moeda>986</moeda>
<data-hora>2013-10-15T00:57:19.032-03:00</data-hora>
<descricao/>
<idioma>PT</idioma>
<taxa-embarque>0</taxa-embarque>
</dados-pedido>
<forma-pagamento>
<bandeira>mastercard</bandeira>
<produto>1</produto>
<parcelas>1</parcelas>
</forma-pagamento>
<status>4</status>
<autenticacao>
<codigo>4</codigo>
<mensagem>Transacao sem autenticacao</mensagem>
<data-hora>2013-10-15T00:57:19.037-03:00</data-hora>
<valor>29900</valor>
<eci>0</eci>
</autenticacao>
<autorizacao>
<codigo>4</codigo>
<mensagem>Transação autorizada</mensagem>
<data-hora>2013-10-15T00:57:19.041-03:00</data-hora>
<valor>29900</valor>
<lr>00</lr>
<arp>123456</arp>
<nsu>661215</nsu>
</autorizacao>
</transacao>
When I run this code, all the elements get right, but not ARP and NSU elements (the last 2 of autorizacao tag)
I really don't know why. This XML comes from a web service and I can't figure out why my deserialize don't work with the 2 last items but works greater with any other element.
I have tried with your code and updated following and it works.
Commented second last <autenticacao> tag.
Rename last tag <autorizacao> to <autenticacao> . May be you are getting wrong xml & last two tags are confusing so I have tried with only one tag.
In Authentication class I have changed type of ARP and NSU otherwise we are getting XMlNode type while deserializing. You can also use string instead of int.
[XmlElement("arp")]
public int arp { get; set; }
[XmlElement("nsu")]
public int nsu { get; set; }

XML serialization array in C#

I'm having trouble figuring this out, I have an xml sheet that looks like this
<root>
<list id="1" title="One">
<word>TEST1</word>
<word>TEST2</word>
<word>TEST3</word>
<word>TEST4</word>
<word>TEST5</word>
<word>TEST6</word>
</list>
<list id="2" title="Two">
<word>TEST1</word>
<word>TEST2</word>
<word>TEST3</word>
<word>TEST4</word>
<word>TEST5</word>
<word>TEST6</word>
</list>
</root>
And I'm trying to serialize it into
public class Items
{
[XmlAttribute("id")]
public string ID { get; set; }
[XmlAttribute("title")]
public string Title { get; set; }
//I don't know what to do for this
[Xml... something]
public list<string> Words { get; set; }
}
//I don't this this is right either
[XmlRoot("root")]
public class Lists
{
[XmlArray("list")]
[XmlArrayItem("word")]
public List<Items> Get { get; set; }
}
//Deserialize XML to Lists Class
using (Stream s = File.OpenRead("myfile.xml"))
{
Lists myLists = (Lists) new XmlSerializer(typeof (Lists)).Deserialize(s);
}
I'm really new with XML and XML serializing, any help would be much appreciated
It should work if you declare your classes as
public class Items
{
[XmlAttribute("id")]
public string ID { get; set; }
[XmlAttribute("title")]
public string Title { get; set; }
[XmlElement("word")]
public List<string> Words { get; set; }
}
[XmlRoot("root")]
public class Lists
{
[XmlElement("list")]
public List<Items> Get { get; set; }
}
If you just need to read your XML into an object structure, it might be easier to use XLINQ.
Define your class like so:
public class WordList
{
public string ID { get; set; }
public string Title { get; set; }
public List<string> Words { get; set; }
}
And then read the XML:
XDocument xDocument = XDocument.Load("myfile.xml");
List<WordList> wordLists =
(
from listElement in xDocument.Root.Elements("list")
select new WordList
{
ID = listElement.Attribute("id").Value,
Title = listElement.Attribute("title").Value,
Words =
(
from wordElement in listElement.Elements("word")
select wordElement.Value
).ToList()
}
).ToList();

Problem creating XML using c#

I am searching a batter solution for creating xml through xml serialization. What i need, i have a given format like this
<product Id="1">
<name>2 1/2 X 6 PVC NIPPLE TOE SCH 80</name>
<notes>
<note>!--note 1---</note>
<note>!--note 2--</note>
......
</notes>
</product>
what i am doing here, i created a 2 classes like this
public class product
{
[XmlElement("name")]
public string Name { get; set; }
[XmlArray("notes")]
public List<notes> ListNotes { get; set; }
}
public class notes
{
[XmlIgnore]
public string Note { get; set; }
}
when i am serializing this then i am getting xml in this formate
<product Id="1">
<name>2 1/2 X 6 PVC NIPPLE TOE SCH 80</name>
<notes>
<notes>
<note>!--note 1---</note>
<note>!--note 2--</note>
</notes>
</notes>
</product>
i don't want extra <notes>. Any batter solution to solve this problem?
Thanks
Solution
public class product
{
[XmlElement("name")]
public string Name { get; set; }
[XmlArray("notes")]
public List<notes> ListNotes { get; set; }
}
public class notes
{
[XmlText]
public string Note { get; set; }
}
product ObjProduct = new product
{
Name ="Pankaj",
notes=new List<note>()
}
foreach (var note in item.ListNote)
{
ObjProduct.notes.Add(new Highmark.BLL.Common.note { Note = EncodeTo64(note.Note) });
}
Now use this ObjProduct for serialization.
Try like this:
[XmlRoot("product")]
public class Product
{
[XmlAttribute]
public int Id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("note")]
public List<Note> ListNotes { get; set; }
}
public class Note
{
[XmlText]
public string Text { get; set; }
}
class Program
{
public static void Main()
{
var p = new Product
{
Id = 1,
Name = "2 1/2 X 6 PVC NIPPLE TOE SCH 80",
ListNotes = new List<Note>
{
new Note { Text = "!--note 1---" },
new Note { Text = "!--note 2---" },
}
};
var serializer = new XmlSerializer(p.GetType());
serializer.Serialize(Console.Out, p);
}
}
And if you want to remove the namespace from the root node:
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
serializer.Serialize(Console.Out, p, ns);
Try like this:
class Program
{
static void Main(string[] args)
{
var product = new Product() { Name = "PVC SCHOOL" };
product.Notes = new List<note>();
product.Notes.Add(new note() { Note = "A" });
product.Notes.Add(new note() { Note = "B" });
var serialer = new XmlSerializer(typeof(Product));
using (var stream = new StreamWriter("test.txt"))
{
serialer.Serialize(stream, product);
}
}
}
public class Product
{
[XmlElement("name")]
public string Name { get; set; }
[XmlArray("notes")]
public List<note> Notes { get; set; }
}
public class note
{
[XmlIgnore]
public string Note { get; set; }
}
This doesn't directly answer your question, but if you can't figure out this problem, you can create a Schema.xsd file, and use .NET's XSD tool to generate the proper serialization classes for you.
I've had pretty good success with that.
The obvious benefit of using a schema is the validation on XML, prior to serialization.

Categories