How to change element name in C# xml serialize? - c#

I am defined a simple class and serialized it:
public class Test
{
public string Name { set; get; }
}
I am serized this simple object,the code like this:
Test test = new Test();
test.Name = "a";
TextWriter writer = new StreamWriter(#"D:\a.xml");
XmlSerializer s = new XmlSerializer(typeof(Test), "");
s.Serialize(writer, test);
writer.Close();
The a.xml result file like this:
<Test xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="">
<Name>a</Name>
</Test>
That's no problem,but now i want my xml node content like this(change the default element name(like: Test) to user define name,whatever the name is(like: job-scheduling-data)):
<job-scheduling-data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="">
<Name>a</Name>
</job-scheduling-data>
What can i do to make it right? I don't want my class name like "job-scheduling-data".

[XmlRoot(ElementName = "job-scheduling-data")]
public class Test
{
public string Name { set; get; }
}
you can check this msdn page.

Related

mixed type property serialization to xml in C#

For example I have three classes
public class A
{
public string Abc { get; set; }
}
public class B
{
public string Xyz { get; set; }
}
public class C
{
private object itemField;
[XmlElement("A", typeof(A))]
[XmlElement("B", typeof(B))]
public object Item
{
get
{
return itemField;
}
set
{
itemField = value;
}
}
}
And I'm trying to serialize an instance of class C
var b = new B
{
Xyz = "123123"
};
var c = new C
{
Item = b
};
var serializer = new XmlSerializer<C>();
var aaa = serializer.Serialize(c);
Then the output is
-C
--A
---Xyz
----123123
---/Xyz
--/A
-/C
But I'm expecting
-C
--B
---Xyz
----123123
---/Xyz
--/B
-/C
How can I do this? (I converted amazon mws xsd's to classes with xsd.exe, and some output classes are like C class, so I'm having trouble while trying to serialize these classes.)
I'm using net framework 4.6.1 and for serialization XSerializer(nuget.org/packages/XSerializer/0.4.2).
*** EDIT: I found the problem, the problem is not the serializer. "xsd.exe" made mistakes on multidimensional arrays while converting xsd files. I edited the classes for serialization attributes and it worked.
Example:
// I changed "[XmlArrayItem("Name", typeof(TypeName))]" To that:
[XmlArrayItem("Name", typeof(TypeName[]))]
public TypeName[][] PropName { get; set; }
Thanks for everyone
I don't know about that nuget, but serializing without nugets (I've used extension method from this post):
var test = SerializeObject<C>(c);
produces expected result
<?xml version="1.0" encoding="utf-16"?>
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<B>
<Xyz>123123</Xyz>
</B>
</C>
I am getting the desired results with XmlSerializer. Namespace System.Xml.Serialization
var writer = new XmlSerializer(typeof(C));
var file = File.Create(strfilepath);
writer.Serialize(file, c);
file.Close();
Output
<?xml version="1.0"?>
<C xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<B>
<Xyz>123123</Xyz>
</B>
</C>

Unit testing XML deserialisation

I am new to unit testing and I am wondering what would be the best practices for unit testing xml deserialisation.
Consider the following xml:
<people>
<person id="1">
<name>Joe</name>
<age>28</age>
</person>
<person id="2">
<name>Jack</name>
<age>38</age>
</person>
</people>
And the following model class for the people:
[XmlRoot(ElementName ="people")]
public class People
{
public People() { PeopleList = new List<Person>(); }
[XmlElement("person")]
public List<Person> PeopleList { get; set; }
}
public class Person
{
[XmlAttribute("id")]
public int id { get; set; }
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("age")]
public int Age { get; set; }
}
I deserialize the xml using:
public List<Person> GetListOfPeople()
{
People plist = new People();
string content;
using (StreamReader sr = new StreamReader(manager.Open("People.xml")))
{
var serializer = new XmlSerializer(typeof(People));
plist = (People)serializer.Deserialize(sr);
}
return plist.PeopleList;
}
What would be the best methods to unit test the GetListOfPeople method above?
If you can change your method to take an xml file as an input parameter, you can have a sample xml file created and added to your test project. Since you know the values of your xml file, you can start comparing the values directly.
Considering you'll use the sample file you provided in your test, you can verify like this:
var persons = x.GetListOfPeople("sample.xml");
Assert.AreEqual("Joe", persons[0].Name);
Assert.AreEqual(38, persons[1].Age);
If the xml file is coming to your code from some source and you think it couldn't be following your xml schema all the time, then probably you can create some sample xml files again which violate your schema and prepare tests to call your method which should throw some exception if schema is not correct.
Hope this helps.

Reading large XML files with C#

I would like to know how can I read a XML file from my desktop and put it into a string?
Here is my XML:
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
I want to store each user, but still detect if their small or big, is there a way to do this?
Before you downrate this, you might want to check google because I did research, but found nothing.
"Before you downrate this, you might want to check google because I
did research, but found nothing"
You found nothing because you don't know what you are searching for, also your XML is invalid, you need to enclose it in a rootElement. Then the first thing you need to do is read this file from the desktop if it exists.
You can check the size if you wish at that time and determine if this is "too large" even though it doesn't really matter. I highly doubt your XML file will be 5+ GB in size. If it is then you need an alternative, no single object in a .Net program may be over 2GB, the best you could do is 1,073,741,823 on a 64bit machine.
For very large XML files, anything above 1.0 GB, combine XmlReader and LINQ as stated by Jon Skeet here:
If your document is particularly huge, you can combine XmlReader and
LINQ to XML by creating an XElement from an XmlReader for each of your
"outer" elements in a streaming manner: this lets you do most of the
conversion work in LINQ to XML, but still only need a small portion of
the document in memory at any one time.
For small XML files, anything 1.0 GB or lower stick to the DOM as shown below.
With that said, what you need is to learn what Serialization and Deserialization mean.
Serialize convert an object instance to an XML document.
Deserialize convert an XML document into an object instance.
Instead of XML you can also use JSON, binary, etc.
In your case this is what can be done to Deserialize this XML document back into an Object in order for you to use in your code.
First fix up the XML and give it a Root.
<?xml version="1.0" encoding="UTF-8"?>
<DataRoot>
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
</DataRoot>
Then create the root class in C#, you may generate this directly in Visual Studio 2012+ by copying your XML and going to Edit - Paste Special, but I like to use: XML to C# Class Generator
Here is what your code would look like after you generate the C# Root Class for your XML, hope it helps you understand it better.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class Program
{
[XmlRoot(ElementName = "user")]
public class User
{
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "motto")]
public string Motto { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "smallusers")]
public class Smallusers
{
[XmlElement(ElementName = "user")]
public List<User> User { get; set; }
}
[XmlRoot(ElementName = "bigusers")]
public class Bigusers
{
[XmlElement(ElementName = "user")]
public User User { get; set; }
}
[XmlRoot(ElementName = "DataRoot")]
public class DataRoot
{
[XmlElement(ElementName = "smallusers")]
public Smallusers Smallusers { get; set; }
[XmlElement(ElementName = "bigusers")]
public Bigusers Bigusers { get; set; }
}
static void Main(string[] args)
{
string testXMLData = #"<DataRoot><smallusers><user id=""1""><name>John</name><motto>I am john, who are you?</motto></user><user id=""2""><name>Peter</name><motto>Hello everyone!</motto></user></smallusers><bigusers><user id=""3""><name>Barry</name><motto>Earth is awesome</motto></user></bigusers></DataRoot>";
var fileXmlData = File.ReadAllText(#"C:\XMLFile.xml");
var deserializedObject = DeserializeFromXML(fileXmlData);
var serializedToXML = SerializeToXml(deserializedObject);
//I want to store each user, but still detect if their small or big, is there a way to do this?
foreach (var smallUser in deserializedObject.Smallusers.User)
{
//Iterating your collection of Small users?
//Do what you need here with `smalluser`.
var name = smallUser.Name; //Example...
}
Console.WriteLine(serializedToXML);
Console.ReadKey();
}
public static string SerializeToXml(DataRoot DataObject)
{
var xsSubmit = new XmlSerializer(typeof(DataRoot));
using (var sw = new StringWriter())
{
using (var writer = XmlWriter.Create(sw))
{
xsSubmit.Serialize(writer, DataObject);
var data = sw.ToString();
writer.Flush();
writer.Close();
sw.Flush();
sw.Close();
return data;
}
}
}
public static DataRoot DeserializeFromXML(string xml)
{
var xsExpirations = new XmlSerializer(typeof(DataRoot));
DataRoot rootDataObj = null;
using (TextReader reader = new StringReader(xml))
{
rootDataObj = (DataRoot)xsExpirations.Deserialize(reader);
reader.Close();
}
return rootDataObj;
}
}
}

XML Serializing Element with prefix

<?xml version="1.0" encoding="UTF-8"?>
<rs:model-request xsi:schemaLocation="http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rs="http://www.ca.com/spectrum/restful/schema/request" throttlesize="100">
<rs:target-models>
I am having trouble understanding the C# XmlSerializer. I have successfully been able to serialize elements that do not have a prefix such as rs:* above. I also have no been able to find how to add the xsi:, xmlns:xsi and xmlns:rs (namespaces?).
Would someone be able to create a simple class to show how to generate the above XML?
Fields, properties, and objects can have a namespace associated with them for serialization purposes. You specify the namespaces using attributes such as [XmlRoot(...)], [XmlElement(...)], and [XmlAttribute(...)]:
[XmlRoot(ElementName = "MyRoot", Namespace = MyElement.ElementNamespace)]
public class MyElement
{
public const string ElementNamespace = "http://www.mynamespace.com";
public const string SchemaInstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";
[XmlAttribute("schemaLocation", Namespace = SchemaInstanceNamespace)]
public string SchemaLocation = "http://www.mynamespace.com/schema.xsd";
public string Content { get; set; }
}
Then you associate the desired namespace prefixes during serialization by using the XmlSerializerNamespaces object:
var obj = new MyElement() { Content = "testing" };
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("xsi", MyElement.SchemaInstanceNamespace);
namespaces.Add("myns", MyElement.ElementNamespace);
var serializer = new XmlSerializer(typeof(MyElement));
using (var writer = File.CreateText("serialized.xml"))
{
serializer.Serialize(writer, obj, namespaces);
}
The final output file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<myns:MyRoot xmlns:myns="http://www.mynamespace.com" xsi:schemaLocation="http://www.mynamespace.com/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<myns:Content>testing</myns:Content>
</myns:MyRoot>

XmlSerialization in C# - root element array

I would like to de/serialize a XML-Document with type=array as root node.
The given xml structure looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<parties type="array">
<party type="Person">
<id>1</id>
<lastname>Smith</lastname>
<firstname>Peter</firstname>
...
</party>
<party type="Person">
<id>2</id>
<lastname>Smith</lastname>
<firstname>Sarah</firstname>
...
</party>
<parties type="array">
C# Code looks like this:
[XmlRootAttribute("parties", Namespace = "", IsNullable = false)]
public class Parties
{
private ArrayList contacts = new ArrayList();
public Parties()
{
}
[XmlArray("parties"), XmlArrayItem("party", typeof(Person))]
public ArrayList Contacts
{
get { return contacts; }
set { contacts = value; }
}
}
The resulting xml output is this:
<?xml version="1.0" encoding="utf-8"?>
<parties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<parties>
<party>
<id>0</id>
<lastname>Smith</last-name>
<firstname>Peter</first-name>
</party>
</parties>
</parties>
The problem is that I have 2 -tags now.
How can I specify array type for the root element? Any ideas how to fix it without changing the given xml schema?
Try this:
[XmlElement("party")]
public ArrayList Contacts
{
get { return contacts; }
set { contacts = value; }
}

Categories