I am using VSTS2008 + C# + .Net 3.0. I am using below code to serialize XML, and my object contains array type property, and I want to add an additional elements' layer ("MyInnerObjectProperties" element layer in my expected results below, and I want to make "MyInnerObjectProperties" element as parent element for all MyInnerObjectProperty element). Any ideas?
Current serialized XML,
<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyObjectProperty>
<MyInnerObjectProperty>
<ObjectName>Foo Type</ObjectName>
</MyInnerObjectProperty>
<MyInnerObjectProperty>
<ObjectName>Goo Type</ObjectName>
</MyInnerObjectProperty>
</MyObjectProperty>
</MyClass>
Expected serialized XML,
<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyObjectProperty>
<MyInnerObjectProperties>
<MyInnerObjectProperty>
<ObjectName>Foo Type</ObjectName>
</MyInnerObjectProperty>
<MyInnerObjectProperty>
<ObjectName>Goo Type</ObjectName>
</MyInnerObjectProperty>
</MyInnerObjectProperties>
</MyObjectProperty>
</MyClass>
Current code,
public class MyClass
{
private MyObject[] _myObjectProperty;
[XmlElement(IsNullable=false)]
public MyObject[] MyObjectProperty
{
get
{
return _myObjectProperty;
}
set
{
_myObjectProperty = value;
}
}
}
public class MyObject
{
private MyInnerObject[] _myInnerObjectProperty;
[XmlElement(IsNullable = false)]
public MyInnerObject[] MyInnerObjectProperty
{
get
{
return _myInnerObjectProperty;
}
set
{
_myInnerObjectProperty = value;
}
}
}
public class MyInnerObject
{
public string ObjectName;
}
public class Program
{
static void Main(string[] args)
{
XmlSerializer s = new XmlSerializer(typeof(MyClass));
FileStream fs = new FileStream("foo.xml", FileMode.Create);
MyClass instance = new MyClass();
instance.MyObjectProperty = new MyObject[1];
instance.MyObjectProperty[0] = new MyObject();
instance.MyObjectProperty[0].MyInnerObjectProperty = new MyInnerObject[2];
instance.MyObjectProperty[0].MyInnerObjectProperty[0] = new MyInnerObject();
instance.MyObjectProperty[0].MyInnerObjectProperty[0].ObjectName = "Foo Type";
instance.MyObjectProperty[0].MyInnerObjectProperty[1] = new MyInnerObject();
instance.MyObjectProperty[0].MyInnerObjectProperty[1].ObjectName = "Goo Type";
s.Serialize(fs, instance);
return;
}
}
make use of the XmlArrayItemAttribute
[XmlArray("MyInnerObjectProperties")]
[XmlArrayItemAttribute("MyInnerObjectProperty", typeof(MyInnerObject), IsNullable = false)]
public MyInnerObject[] MyInnerObjectProperty
{
get
{
return _myInnerObjectProperty;
}
set
{
_myInnerObjectProperty = value;
}
}
...
[XmlArray(IsNullable = false)]
[XmlArrayItem("MyInnerObjectProperties")]
public MyObject[] MyObjectProperty
{
get
{
return _myObjectProperty;
}
set
{
_myObjectProperty = value;
}
}
...
Related
I have a class defined that auto increments a property in its get method. I am trying to serialize this object to an XML and the auto-incremented property is not being printed. Any help is appreciated.
public class Program
{
public static void Main()
{
MyClass _myClass = new MyClass();
string transactionXML = string.Empty;
Console.WriteLine("Current ID: " + _myClass.ID);
System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(MyClass));
System.IO.StringWriter _sw = new System.IO.StringWriter();
System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(_sw);
xmlSerializer.Serialize(writer, _myClass);
transactionXML = _sw.ToString();
Console.WriteLine("XML:\n" + transactionXML);
}
[Serializable]
public class MyClass
{
long last_id = 0;
public string ID{get { return System.Threading.Interlocked.Increment(ref last_id ).ToString("D6"); }}
}
}
When I try to run this, it runs with no errors, but does not print the ID in the XML.
you need to extend you "MyClass" ID with a setter like this:
[Serializable]
public class MyClass
{
long last_id = 0;
public string ID { get { return System.Threading.Interlocked.Increment(ref last_id).ToString("D6"); } set { } }
}
Limitation of XMLSerializer - Properties without a setter can't be serialized.
But you can use DataContractSerializer to serialize private setter properties -
[DataMember]
public string Id
{
get
{
return Guid.NewGuid().ToString();
}
private set {}
}
I am using an asp.net and C# to serialize some entered data using a class. This class was generated from an xsd file. I am using this class to generate an xml file. I am struggling to understand how I can reference all these classes and serialize it to one xml file.
Here is my class code. It is in a separate file within my project:
namespace Ce
{
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.33440.
//
public partial class AddRequest
{
private CDocument cDocumentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public CDocument CDocument
{
get
{
return this.cDocumentField;
}
set
{
this.cDocumentField = value;
}
}
}
public partial class CDocument
{
private CaseA caseAField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public CaseA CaseA
{
get
{
return this.caseAField;
}
set
{
this.caseAField = value;
}
}
}
public partial class CaseA
{
public string dCTextField;
private string dLField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public string DCText
{
get
{
return this.dCTextField;
}
set
{
this.dCTextField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "x")]
public string DLU
{
get
{
return this.dLField;
}
set
{
this.dLField = value;
}
}
}
}
To serialize I have this in my code-behind in a button click event:
protected void CaseSubmitButton_Click(object sender, EventArgs e)
{
CaseA CSerialize = new CaseA();
CSerialize.DCText = casetextboxt.text;
CSerialize.DLu = "\\app";
XmlSerializer Serializer = new XmlSerializer(typeof(CaseA));
StreamWriter Writer = new StreamWriter(Server.MapPath("~/XmlPackages/" + xmlPackageFilename));
Serializer.Serialize(Writer, CSerialize);
Serializer.Serialize(Writer, CSerialize);
}
With this button click event I get this xml format:
<?xml version="1.0" encoding="utf-8"?>
<CaseA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DCText>\apptest</DCText>
<DLU>\apptest</DLU>
</CaseA>
I would like to reference the other two classes to get:
<?xml version="1.0" encoding="utf-8"?>
<Addrequest>
<Cdocument>
<CaseA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DCText>\apptest</DCText>
<DLU>\apptest</DLU>
</CaseA>
</Cdocument>
</Addrequest>
You're serializing an instance of CaseA class, which is why you're only seeing members of CaseA in the output. You need to create an instance of AddRequest and serialize that as the root, something like this:
CaseA cSerialize = new CaseA();
cSerialize .DCText = casetextboxt.text;
cSerialize .DLu = "\\app";
CDocument document = new CDocument();
document.CaseA = cSerialize ;
AddRequest root = new AddRequest();
root.CDocument = document;
XmlSerializer serializer = new XmlSerializer(typeof(AddRequest), new Type[] { typeof(CDocument), typeof(CaseA) });
StreamWriter writer = new StreamWriter(Server.MapPath("~/XmlPackages/" + xmlPackageFilename));
serializer.Serialize(writer, root);
As a side note, please follow C# coding standards for naming your local variables :)
I have a very very strange problem. I would like to serialize a object via xml.
Ok so I started creating a XmlSerializer and there was no error - nothing.
But if i deserialize... the properties are just not set. Another strange thing is that the xml seems to be ok.
this is a part of my code the rest are just methods...
[XmlInclude(typeof(TestMapper))]
[XmlInclude(typeof(TestSource))]
[XmlInclude(typeof(TestTarget))]
public abstract class ElementBase : IElement
{
[XmlIgnore]
public IElement this[int index]
{
get
{
return Childs.ElementAt(index).Value;
}
}
List<ElementBase> _childSerializable;
[XmlArrayItem(typeof(ElementBase))]
public List<ElementBase> ChildSerializable
{
get
{
_childSerializable = Childs.Select(x => x.Value).ToList();
return _childSerializable;
}
set
{
_childSerializable = value;
foreach (ElementBase element in _childSerializable)
Childs.Add(element.Index, element);
}
}
protected Dictionary<object, ElementBase> _childs;
[XmlIgnore]
public Dictionary<object, ElementBase> Childs
{
get
{
return _childs ?? (_childs = new Dictionary<object ,ElementBase>());
}
set
{
_childs = value;
}
}
object _index = -1;
public object Index
{
get
{
return _index;
}
set
{
_index = value;
}
}
And this is how i serialize:
TestTarget target = new TestTarget();
TestSource source = new TestSource() { Value = "Hallo", Index = 1};
TestSource source1 = new TestSource() { Value = " Welt", Index = 2};
TestMapper mapper = new TestMapper();
target.ConnectChild(mapper);
mapper.ConnectChild(source);
mapper.ConnectChild(source1);
target.Execute();
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
XmlSerializer serializer = new XmlSerializer(target.GetType());
serializer.Serialize(memStream, target);
memStream.Position = 0;
object obj = serializer.Deserialize(memStream);
target = obj as TestTarget;
memStream.Position = 0;
Console.ReadKey();
Ok so now and this is the final result:
<?xml version="1.0"?>
<TestTarget xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ChildSerializable>
<ElementBase xsi:type="TestMapper">
<ChildSerializable>
<ElementBase xsi:type="TestSource">
<ChildSerializable />
<Index xsi:type="xsd:int">1</Index>
<Value xsi:type="xsd:string">Hallo</Value>
</ElementBase>
<ElementBase xsi:type="TestSource">
<ChildSerializable />
<Index xsi:type="xsd:int">2</Index>
<Value xsi:type="xsd:string"> Welt</Value>
</ElementBase>
</ChildSerializable>
<Index xsi:type="xsd:int">-1</Index>
</ElementBase>
</ChildSerializable>
<Index xsi:type="xsd:int">-1</Index>
</TestTarget>
So does anyone has any idea what happend wrong. I am working since a few hours on it but i can t find anything :((
It seems to be related to the fact that you are using a List<ElementBase>. If you use a simple array like ElementBase[], the items are deserialized.
There are some explanation here, but nothing I found satisfactory.
How can I change XML-element name for field inherited from base class while doing serialization?
For example I have next base class:
public class One
{
public int OneField;
}
Serialization code:
static void Main()
{
One test = new One { OneField = 1 };
var serializer = new XmlSerializer(typeof (One));
TextWriter writer = new StreamWriter("Output.xml");
serializer.Serialize(writer, test);
writer.Close();
}
I get what I need:
<?xml version="1.0" encoding="utf-8"?>
<One xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OneField>1</OneField>
</One>
Now I have created new class inherited from A with additional field and custom XML element name for it:
public class Two : One
{
[XmlElement("SecondField")]
public int TwoField;
}
Serialization code:
static void Main()
{
Two test = new Two { OneField = 1, TwoField = 2 };
var serializer = new XmlSerializer(typeof (Two));
TextWriter writer = new StreamWriter("Output.xml");
serializer.Serialize(writer, test);
writer.Close();
}
As a result I get next output:
<?xml version="1.0" encoding="utf-8"?>
<Two xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<OneField>1</OneField>
<SecondField>2</SecondField>
</Two>
The problem is that I want to change OneField in this output to FirstField without touching base class code (because I will use it too and the names must be original). How can I accomplish this?
Thank you.
Try this:
public class Two : One
{
private static XmlAttributeOverrides xmlOverrides;
public static XmlAttributeOverrides XmlOverrides
{
get
{
if (xmlOverrides == null)
{
xmlOverrides = new XmlAttributeOverrides();
var attr = new XmlAttributes();
attr.XmlElements.Add(new XmlElementAttribute("FirstField"));
xmlOverrides.Add(typeof(One), "OneField", attr);
}
return xmlOverrides;
}
}
[XmlElement("SecondField")]
public string TwoField;
}
And your serializer init is a lot easier:
var xmls = new System.Xml.Serialization.XmlSerializer(typeof(Two), Two.XmlOverrides);
Here's a workaround: Override the fields in the subclass and mark the overriden field with whatever name you need. For example,
class One
{
public int OneField { get; set; }
}
class Two : One
{
[XmlElement("FirstField")]
public new int OneField
{
get { return base.OneField; }
set { base.OneField = value; }
}
}
I am using VSTS2008 + C# + .Net 3.0. I am using below code to serialize XML, here is my current code and serialized XML file. My purpose is I want to make MyInnerObjectProperties belongs to a special XML namespace (http://foo/2009) and making this namespace as default namespace. Any ideas how to implement this?
Current output:
<?xml version="1.0"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyObjectProperty>
<MyInnerObjectProperties>
<MyInnerObjectProperty>
<ObjectName>Foo Type</ObjectName>
</MyInnerObjectProperty>
<MyInnerObjectProperty>
<ObjectName>Goo Type</ObjectName>
</MyInnerObjectProperty>
</MyInnerObjectProperties>
</MyObjectProperty>
</MyClass>
Current code:
public class MyClass
{
private MyObject[] _myObjectProperty;
[XmlElement(IsNullable=false)]
public MyObject[] MyObjectProperty
{
get
{
return _myObjectProperty;
}
set
{
_myObjectProperty = value;
}
}
}
public class MyObject
{
private MyInnerObject[] _myInnerObjectProperty;
[XmlArrayItemAttribute("MyInnerObjectProperty", typeof(MyInnerObject), IsNullable=false)]
public MyInnerObject[] MyInnerObjectProperties
{
get
{
return _myInnerObjectProperty;
}
set
{
_myInnerObjectProperty = value;
}
}
}
public class MyInnerObject
{
public string ObjectName;
}
public class Program
{
static void Main(string[] args)
{
XmlSerializer s = new XmlSerializer(typeof(MyClass));
FileStream fs = new FileStream("foo.xml", FileMode.Create);
MyClass instance = new MyClass();
instance.MyObjectProperty = new MyObject[1];
instance.MyObjectProperty[0] = new MyObject();
instance.MyObjectProperty[0].MyInnerObjectProperties = new MyInnerObject[2];
instance.MyObjectProperty[0].MyInnerObjectProperties[0] = new MyInnerObject();
instance.MyObjectProperty[0].MyInnerObjectProperties[0].ObjectName = "Foo Type";
instance.MyObjectProperty[0].MyInnerObjectProperties[1] = new MyInnerObject();
instance.MyObjectProperty[0].MyInnerObjectProperties[1].ObjectName = "Goo Type";
s.Serialize(fs, instance);
return;
}
}
How about this:
[XmlArrayItemAttribute( Namespace = "http://foo.com/2009" /* other attr. params. */ )]
public MyInnerObject[] MyInnerObjectProperties
{
get { ... }
set { ... }
}
Try
public class MyObject
{
[XmlArrayItemAttribute("MyInnerObjectProperty", typeof (MyInnerObject),
IsNullable = false)]
[XmlArray(Namespace = "http://foo.com/2009")]
public MyInnerObject[] MyInnerObjectProperties { get; set; }
}
for me, this produces:
<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyObjectProperty>
<MyInnerObjectProperties xmlns="http://foo.com/2009">
<MyInnerObjectProperty>
<ObjectName>Foo Type</ObjectName>
</MyInnerObjectProperty>
<MyInnerObjectProperty>
<ObjectName>Goo Type</ObjectName>
</MyInnerObjectProperty>
</MyInnerObjectProperties>
</MyObjectProperty>
</MyClass>
You need to create an XmlSerializerNamespaces object, and add your needed namespaces to it.
The XmlSerializerNamespaces object contains the XML namespaces and prefixes that the XmlSerializer uses to generate qualified names in an XML-document instance.
In your c# code:
XmlSerializerNamespaces myNameSpaces = new XmlSerializerNamespaces();
myNameSpaces.Add("MyInnerObject", "http://foo/2009");
Then, add an attribute to your class, like this:
public class MyInnerObject
{
[XmlElement(Namespace = "http://foo/2009")]
More info at:
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializernamespaces.aspx