[XmlRoot("Class1")]
class Class1
{
[(XmlElement("Product")]
public string Product{get;set;}
[(XmlElement("Price")]
public string Price{get;set;}
}
This is my class. In this the price contains the '£' symbol. after serializing it to XML I get the '?' instead of '£'.
what I need to do to get the '£' in XML? OR How can I pass the data in price as CDATA?
Your problem must be to do with how the XML is written to the file.
I've written a program that uses the information that you've given me so far, and it when I print the XML string out, it is correct.
I conclude that the error is happening either when the data is written to the XML file, or when it is read back in from the XML file.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
new Program().Run();
}
void Run()
{
Class1 test = new Class1();
test.Product = "Product";
test.Price = "£100";
Test(test);
}
void Test<T>(T obj)
{
XmlSerializerNamespaces Xsn = new XmlSerializerNamespaces();
Xsn.Add("", "");
XmlSerializer submit = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
XmlWriter writer = XmlWriter.Create(stringWriter);
submit.Serialize(writer, obj, Xsn);
var xml = stringWriter.ToString(); // Your xml This is the serialization code. In this Obj is the object to serialize
Console.WriteLine(xml); // £ sign is fine in this output.
}
}
[XmlRoot("Class1")]
public class Class1
{
[XmlElement("Product")]
public string Product
{
get;
set;
}
[XmlElement("Price")]
public string Price
{
get;
set;
}
}
}
Related
Trying to create an XML file of the following structure:
<Objects>
<ArrayOfObject1>
<Object1>
<Object1>
</ArrayOfObject1>
<ArrayOfObject2>
<Object2>
<Object2>
</ArrayOfObject2>
</Objects>
Is there any way to achieve this using the XmlSerializer? I'm aware that the following code snippet can be used to generate an XML file that has a root node of ArrayOfObject1 and elements corresponding to every object in the list; I'd just like to extend this to have a different root node, and an array of each object within it.
XmlSerializer serializer = new XmlSerializer(typeof(List<Object1>));
Of course, it may be best practice to have two different XML files, but I'm just trying to find out if there's an acceptable/sensible way to have two arrays of objects represented in a single file.
Thanks!
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Objects));
Objects objects = new Objects()
{
objects1 = new List<Object1>()
{
new Object1(), new Object1()
},
objects2 = new List<Object2>()
{
new Object2(), new Object2()
}
};
serializer.Serialize(writer, objects);
}
}
public class Objects
{
[XmlArray("ArrayOfObject1")]
[XmlArrayItem("Object1")]
public List<Object1> objects1 { get; set; }
[XmlArray("ArrayOfObject2")]
[XmlArrayItem("Object2")]
public List<Object2> objects2 { get; set; }
}
public class Object1
{
}
public class Object2
{
}
}
I do have a problem with serialization of a namespaces. As my code show below my logic fills the structure of my dictionary, serializes it and puts into a string variable. I use this variable to load into XMLDocument and after that I do add the namespaces. But since they are added after the serialization process the namespaces are set in UTF8? Should I add namespaces before serialization? If yes, how can I do it properly?
///Dictionary
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace TestXML
{
[Serializable]
[XmlRoot(ElementName = "Root")]
public class XMLSchema: Serialization
{
[XmlElement(ElementName = "Element1")]
public XMLElement1 Element1 { get; set; }
[XmlElement(ElementName = "Element2")]
public XMLElement2 Element2 { get; set; }
}
}
///Serialization class
public class Utf8StringWriter : StringWriter
{
// Use UTF8 encoding
public override Encoding Encoding
{
get { return new UTF8Encoding(false); }
}
}
public string Serialize()
{
var xmlserializer = new XmlSerializer(this.GetType());
var Utf8StringWriter = new Utf8StringWriter();
var xns = new XmlSerializerNamespaces();
xns.Add(string.Empty, string.Empty);
using (var writer = XmlWriter.Create(Utf8StringWriter))
{
xmlserializer.Serialize(writer, this, xns);
return Utf8StringWriter.ToString();
}
}
///create xml
str xml;
[...] my logic to add data into elements
XmlDocument doc = new XmlDocument();
xml = XMLSchema.Serialize();
doc.LoadXml(xml);
XmlElement root = doc.getNamedElement("Root");
root.SetAttribute("xmlns:etd", "http://google.com");
root.SetAttribute("xmlns:xsi", "http://google.com");
root.SetAttribute("xmlns", "http://google.com");
doc.AppendChild(root);
doc.Save(path);
Edit. Adding provided sample.
<?xml version="1.0" encoding="UTF-8"?> <XMLSample xmlns="http://crd.gov.pl/wzor/" xmlns:xsi="http://www.w3.org/2001/" xmlns:etd="http://crd.gov.pl/xml/schematy/">
So to give you an example (based on your sample):
[XmlRoot("XMLSample", Namespace = "http://crd.gov.pl/wzor/")]
public class XmlSample
{
[XmlElement]
public string Element1 { get; set; }
[XmlElement(Namespace = "http://crd.gov.pl/xml/schematy/")]
public string Element2 { get; set; }
}
Here, the root has the namespace http://crd.gov.pl/wzor/. Element1 inherits that namespace (as none is specified). Element2 has the namespace http://crd.gov.pl/xml/schematy/.
When this is serialised, the serialiser will use the root namespace as the default, so there's no need to explicitly set this. You can set the others to use the prefixes as defined in your sample:
var xsn = new XmlSerializerNamespaces();
xsn.Add("xsi", "http://www.w3.org/2001/");
xsn.Add("etd", "http://crd.gov.pl/xml/schematy/");
You can see this fiddle for a demo, the output is:
<?xml version="1.0" encoding="utf-8"?>
<XMLSample xmlns:xsi="http://www.w3.org/2001/" xmlns:etd="http://crd.gov.pl/xml/schematy/" xmlns="http://crd.gov.pl/wzor/">
<Element1>foo</Element1>
<etd:Element2>bar</etd:Element2>
</XMLSample>
Note that Element2 uses the prefix configured for its namespace.
How to create a C# class which must be used to deserialize the XML as given below
<?xml version="1.0" encoding="utf-8"?>
<XML>
<StatusCode>-2</StatusCode>
<Warnings />
<Errors>
<Error> Debtor #2 Invalid Postal Code</Error>
<Error>Invalid lien term</Error>
</Errors>
</XML>
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication110
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.xml";
const string OUTPUT_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(INPUT_FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(XML));
XML xml = (XML)serializer.Deserialize(reader);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME, settings);
serializer.Serialize(writer, xml);
}
}
public class XML
{
public int StatusCode { get; set; }
public string Warnings { get; set; }
[XmlArray("Errors")]
[XmlArrayItem("Error")]
public List<string> errors { get; set; }
}
}
To create classes based on XML, copy the xml to the clipboard, then in Visual Studio 2017, choose the menu option: Edit/Paste Special/Paste XML as classes.
Your Class should look like:
public class ErrorClass
{
struct Error
{
public String message;
}
struct Warning
{
public String message;
}
int StatusCode;
List<Error> Errors;
List<Warning> Warnings;
}
Error and Warning struct could contain more items that are not used in the example you posted.
I have an XML document I'm trying to deseralize that has a attribute that is ref which in C# can not be used to declare a variable hence the below doesn't work
[XmlAttribute()]
public string ref;
Anyway to get this to deseralize properly? I know it is case sensitive so Ref wouldn't work.
You can provide a name in the attribute:
[XmlAttribute("ref")]
public string anynameyouwant;
You can change the attribute name in the xml file, by using the AttributeName, such as in the following example:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace soans
{
public class Test
{
//problematic attribute (ref is reserved)
[XmlAttribute(AttributeName="ref")]
public string RefAttr {get;set;}
//other attributes as well
[XmlAttribute()]
public string Field { get; set; }
}
class Program
{
static void Main(string[] args)
{
string filename = ""; //use your path here
Test original = new Test()
{
RefAttr = "ref",
Field = "test"
};
//serialiser
XmlSerializer ser = new XmlSerializer(typeof(Test));
//save to file
TextWriter writer = new StreamWriter(filename);
ser.Serialize(writer, original);
writer.Close();
//read from file
TextReader reader = new StreamReader(filename);
var fromfile = ser.Deserialize(reader) as Test;
if(fromfile!=null)
{
Console.WriteLine(fromfile.RefAttr);
}
reader.Close();
Console.ReadKey();
}
}
}
Can some one help for a strange Serialization issue which I getting in a one environment and it working fine in all environments..but it failed a particular environment..so I specified as strange here
Code
public SomeType[] Deserialize(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(SomeType[]));
StringReader stringReader = new StringReader(xml);
SomeType[] types = (SomeType[])serializer.Deserialize(stringReader);
stringReader.Close();
return types;
}
Serialized XML data:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSomeType>
<SomeType>
<Field1>val</Field1>
<Field2>val</Field2>
<Field3>val</Field3>
</SomeType>
</ArrayOfSomeType>
And the exception is:
System.InvalidCastException: Unable to cast object of type 'SomeType[]' to type 'SomeType'.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterSomeType.Write11_SomeType(Object o)
The error here is in the Serialize method that you don't show. Your Deserialize method works without error. The following Serialize method works fine:
static string Serialize(SomeType[] values)
{
using (var sw = new StringWriter())
{
var serializer = new XmlSerializer(typeof(SomeType[]));
serializer.Serialize(sw, values);
return sw.ToString();
}
}
If I had to guess, you have the following:
var serializer = new XmlSerializer(typeof(SomeType));
If you want the exact same output without unnecessary namespace alias declarations, change the method to include:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
serializer.Serialize(sw, values, ns);
Edit showing the current code working fine:
using System;
using System.IO;
using System.Xml.Serialization;
public class SomeType
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
public class MyTest
{
public static SomeType[] Deserialize(string xml)
{
XmlSerializer serializer = new XmlSerializer(typeof(SomeType[]));
StringReader stringReader = new StringReader(xml);
SomeType[] types = (SomeType[])serializer.Deserialize(stringReader);
stringReader.Close();
return types;
}
public static void Main()
{
string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<ArrayOfSomeType>
<SomeType>
<Field1>val</Field1>
<Field2>val</Field2>
<Field3>val</Field3>
</SomeType>
</ArrayOfSomeType>";
var items = Deserialize(xml);
foreach (var item in items)
{
Console.WriteLine("{0}, {1}, {2}",
item.Field1, item.Field2, item.Field3);
}
}
}