XML Serialize C# - c#

I'm using
List<EFacebook> facebooks = BFacebook.ReadFacebookFriends(user.EProviders
.Where(i => i.ProviderType == EProvider.EnumProviderType.Facebook)
.First().Token);
StringBuilder xml = new StringBuilder();
foreach (EFacebook i in facebooks)
{
xml.AppendFormat("<id>{0}</id>", i.id);
}
Can anybody suggest a better code to serialize each i.id into an XML string?
Edit:
The facebook object has close to 20 properties. If I XmlSerializer all 20 properties are serialized into the XML. I just need the id column.

You might want to take a look at XML Serialization already built into the .NET Framework.
You can use code similar to the following to serialize the object:
MySerializableClass myObject = new MySerializableClass();
// Insert code to set properties and fields of the object.
XmlSerializer mySerializer = new
XmlSerializer(typeof(MySerializableClass));
// To write to a file, create a StreamWriter object.
StreamWriter myWriter = new StreamWriter("myFileName.xml");
mySerializer.Serialize(myWriter, myObject);
myWriter.Close();
See: How to serialize
You can flag properties to be ignored using the XmlIgnore attribute as shown below:
public class Group
{
// The XmlSerializer ignores this field.
[XmlIgnore]
public string Comment;
// The XmlSerializer serializes this field.
public string GroupName;
}
See XMLIgnore

XmlSerializer xs = new XmlSerializer(typeof(int[]));
xs.Serialize(stream,facebooks.Select(x=>x.id).ToArray())

I would use Linq To Xml to create the Xml Tree structure
See for an example: Linq To Xml

If you're just saving the id values into an xml string then I wouldn't say that you're 'serializing' the objects.
Whenever working with XML it's much nicer to use an XML library than to wrangle with text. One obvious reason is that it guarantees your XML will be well-formed.
I'd do something like this:
List<EFacebook> facebooks = GetFriends();
var facebookIds = facebooks.Select(f => new XElement("id", f.id));
var facebookXml = new XElement("facebookIds", facebookIds);
Which will give you XML like
<facebookIds>
<id>1</id>
<id>2</id>
</facebookIds>

Related

Adding an attribute to the root XML element when serializing an object

I have an object that I serialize into an XML file. Everything works as expected, but I'm wanting to add a Version attribute to the root element.
What's the best way to do this?
Here's an example of how I'm serializing:
MyProgram newProgram = new MyProgram()
{
ValueA = "A value.",
ValueB = "B value.",
ValueC = "C value."
};
XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyProgram));
StreamWriter streamWriter = new StreamWriter(fileName);
xmlSerializer.Serialize(streamWriter, newProgram);
streamWriter.Close();
Right now, my XML looks something like this:
<MyProgram>
<ValueA>A value.</ValueA>
<ValueB>B value.</ValueB>
<ValueC>C value.</ValueC>
</MyProgram>
But I'd like to have this:
<MyProgram Version="1.0">
<ValueA>A value.</ValueA>
<ValueB>B value.</ValueB>
<ValueC>C value.</ValueC>
</MyProgram>
Thanks!
First
Modify your XML to be like this, assuming you have a concrete class and not an anonymous one
[XmlRoot("MyProgram")]//sepcifies the name of the root element
public class MyProgram
{
[XmlAttribute("Version")]//name not required unless you want to change output to something different
public string Version{get;set;}
[XmlElement("ValueA")]//again, name not required if the name is the same
public ValueA ValueA{get;set;}
....
}
Then creating the MyProgram class as you specified will give you the desired output, also note that you might need to add XML tags to the ValueA/B/C classes if the end result is not as desired.
The second
Serialize the XML data to a string, and use simple Regex/String manipulation to insert the desired value and then save the string to the desired location
Third
You can either use XElement to query your XML string /Create it and then set the Version attribute
XElement x = XElement.Load("Your XML location");
var yourRoot = x.Descendants("MyProgram").FirstOrDefaul();
yourRoot.SetAttributeValue("Version","1.0");
yourRoot.Save("Your XML location");

Saving object state using xml Serializer. Recommend approach for getting node name from property or hardcoded string?

We are trying to save state of our object using XML serializer. For discussion assume object to be like:
Class Program
{
public string Char1 {get; set;}
public XMLNode Serialize (XmlDocument doc)
{
var node = document.CreateElement("Mod")
node.SetAttribute("Char1", Char1.ToString());
}
}
Here we are getting the value of property Char1 and trying to write it in a node with name Char1.
Is it better to have the node name "Char1" be derived from Char1 property using reflection. But this could result in changing the XML document often when property name is changed.
If property name is changed and the string is not updated then the value in xml document will not match the context of that field.
What approach is preferable?
Please suggest if there is any other better approach to avoid magic strings while writing xml file.
I would prefer following way: Create a class which holds all your data you want wo serialize. Then create an instance of the XmlSerializer like this
xmlDocument = new XmlDocument();
using (var stringWriter = new StringWriter(CultureInfo.InvariantCulture))
{
using (var xmlTextWriter = new XmlTextWriter(stringWriter))
{
xmlTextWriter.Formatting = Formatting.Intented;
var xmlSerializer = new XmlSerializer(myObject.GetType());
xmlSerializer.Serialize(xmlTextWriter, myObject);
xmlDocument.PreserveWhitespace = true;
xmlDocument.LoadXml(stringWriter.ToString());
}
}

How to retain XML string as a string field during XML deserialization

I got an XML input string and want to deserialize it to an object which partially retain the raw XML.
<SetProfile>
<sessionId>A81D83BC-09A0-4E32-B440-0000033D7AAD</sessionId>
<profileDataXml>
<ArrayOfProfileItem>
<ProfileItem>
<Name>Pulse</Name>
<Value>80</Value>
</ProfileItem>
<ProfileItem>
<Name>BloodPresure</Name>
<Value>120</Value>
</ProfileItem>
</ArrayOfProfileItem>
</profileDataXml>
</SetProfile>
The class definition:
public class SetProfile
{
public Guid sessionId;
public string profileDataXml;
}
I hope the deserialization syntax looks like
string inputXML = "..."; // the above XML
XmlSerializer xs = new XmlSerializer(typeof(SetProfile));
using (TextReader reader = new StringReader(inputXML))
{
SetProfile obj = (SetProfile)xs.Deserialize(reader);
// use obj ....
}
but XMLSerializer will throw an exception and won't output < profileDataXml >'s descendants to "profileDataXml" field in raw XML string.
Is there any way to implement the deserialization like that?
If you want to deserialize that as XML, then use an XML type (either XElement or XmlElement should work) - see code below.
public class StackOverflow_11234676
{
const string XML = #"<SetProfile>
<sessionId>A81D83BC-09A0-4E32-B440-0000033D7AAD</sessionId>
<profileDataXml>
<ArrayOfProfileItem>
<ProfileItem>
<Name>Pulse</Name>
<Value>80</Value>
</ProfileItem>
<ProfileItem>
<Name>BloodPresure</Name>
<Value>120</Value>
</ProfileItem>
</ArrayOfProfileItem>
</profileDataXml>
</SetProfile>";
public class SetProfile
{
public Guid sessionId;
public XElement profileDataXml;
}
public static void Test()
{
string inputXML = XML;
XmlSerializer xs = new XmlSerializer(typeof(SetProfile));
using (TextReader reader = new StringReader(inputXML))
{
SetProfile obj = (SetProfile)xs.Deserialize(reader);
Console.WriteLine(obj.profileDataXml);
}
}
}
I would say that you can deserialize this XML.
Take a look at this article:
Attributes That Control XML Serialization
Easiest way to get it working is to use REVERSE approach. Create classes and apply xml serialization attributes and experiment with serialization until you get the same xml result as posted. Once you get the same xml, your deserialization will work.
I would use Xml.Linq for this.
setProfile obj = new setProfile();
var doc = XDocument.Parse(yourXml);
obj.sessionID = doc.Root.Element("sessionID").value;
obj.profileDataXml = doc.Root.Element("profileDataXml").value;

Creating an Entity from XML

I have the following XML structure
<T>
<F>
<H>
<H1>some value</H1>
<H2>some value</H2>
<H3>some value</H3>
</H>
<O>
<P>some value</P>
<TI>some value</TI>
<TI>some value</TI>
</O>
<R>
<PTY>some value</PTY>
<PTY>some value</PTY>
<PTY>some value</PTY>
</R>
</F>
<T>
I need to parse this xml in C# and get the values out of them to be further exported to a CSV file.
My query is how do you go about creating an entity for this XML
You can play with XmlSerializer and its related attributes.
As long as the XML is not too complex, there's not much work to do.
To read the XML:
var serializer = new XmlSerializer(typeof(SerializableObject));
SerializableObject deserialized;
using (var stream = new FileStream(#"C:\test.xml", FileMode.Open))
{
deserialized = (SerializableObject)serializer.Deserialize(stream);
}
The SerializableObject will look like this:
[Serializable]
[XmlRootAttribute("T")]
public class SerializableObject
{
...
}
BONUS for lazy programmers: You can just use Xsd.exe to brute force create an object from an XML file. Then tweak the results to your needs.
You can use LinqToXml to parse xml. StringBuilder will be helpful to produce CSV.
I think these How Tos will be useful. They describe all you needed to parse this xml.
add using System.Xml.Linq;
then you can do something similar to this:
XDocument xml = XDocument.Load(#"....\People.xml");
var query = from p in xml.Elements("people").Elements("person")
where (int)p.Element("id") == 1
select p;

XmlSerializer Deserializing Array/List of Multiple Objects at Root

I'm trying to deserialize the following XML output:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Foo>
<Val>Data1</Val>
</Foo>
<Foo>
<Val>Data2</Val>
</Foo>
(This is output from a hardware device, and cannot be changed)
I have an XML type defined as:
[XmlType(AnonymousType=true, Namespace="")]
public class Foo
{
public string Val { get; set; }
}
I've tried to deserialize this array by creating a serializer like:
var s = new XmlSerializer(typeof(Foo[]));
//or
var s = new XmlSerializer(typeof(List<Foo>);
But every call to s.Deserialize() causes an InvalidOperaitonException:
System.InvalidOperationException: <Foo xmlns=''> was not expected.
Note
var s = new XmlSerializer(typeof(Foo));
// Only deseralizes the first Foo (Data1).
Thanks for your help.
I think the issue is with your provided xml.
Test app says
List<Foo> list = new List<Foo> {new Foo {Val = "Data1"}, new Foo {Val = "Data2"}};
var s = new XmlSerializer(typeof(List<Foo>));
StringBuilder sb = new StringBuilder();
XmlWriter wr = XmlWriter.Create(sb);
s.Serialize(wr, list);
string ss = sb.ToString();
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);
And the XML should be
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfFoo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Foo>
<Val>Data1</Val>
</Foo>
<Foo>
<Val>Data2</Val>
</Foo>
</ArrayOfFoo>
If you can remove the inital line
<?xml version="1.0" encoding="ISO-8859-1"?>
And minipulate the string into
string s = "<ArrayOfFoo><Foo> <Val>Data1</Val></Foo><Foo> <Val>Data2</Val></Foo></ArrayOfFoo>";
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(s);
List<Foo> list = (List<Foo>)s2.Deserialize(sr);
That could work.
That isn't valid Xml. There needs to be a core root element for it to work properly.
this is not a valid xml so you can not deserialize it like a valid xml. You need some kind of hack to make this work. i'd suggest to insert at beginning of the xml and inserting at the end of xml. then you can deserialize it, since you cant make this change at xml side, do it in your code.
String ss;
// lets assume this holds your xml data in string.
ss.append("</ArrayOfFoo>");
ss.replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "<?xml version=\"1.0\" encoding=\"utf-16\"?> <ArrayOfFoo>")
var s2 = new XmlSerializer(typeof(List<Foo>));
StringReader sr = new StringReader(ss);
List<Foo> returnList = (List<Foo>)s2.Deserialize(sr);
now this shall return you the correct list.
As the other posters say, this XML that the hardware device produces is not compatible to the way .NET serializes/deserializes object. Valid XML, and .NET requires valid XML, has a root element.
I suggest:
either you modify your obtained XML to match the way astander presents in his xml code snippet.
or you write a simple xml parser for your file that deserializes the file like you need
br, Marcel
Technically, what you have there is not a well-formed XML document (which has exactly one root element), but rather an well-formed external parsed entity (which can have any number of elements not contained in other elements, as well as text not contained in any elements). Therefore, it should parse if your XML parser has an entry point for parsing EPEs rather than documents. You could also create a stub document which includes by reference your EPE and parse that document.
Xstream for .Net could be a useful API

Categories