I need to replicate this XML structure with class instances but I am failing on the xmlAttribute xsi:type="array"
This is my plain class setup, I tried a hundred things from various posts and tutorials like XmlInclude but i can't seem to make it work:
private ST_DtxInstance dtxFile = new ST_DtxInstance();
[System.Xml.Serialization.XmlRootAttribute(ElementName = "Database", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2", IsNullable = false)]
public class ST_DtxInstance
{
[XmlArray("Datas")]
[XmlArrayItem("Data")]
public ST_Data[] csDatas = new ST_Data[] { new ST_Data(), new ST_Data() };
}
public class ST_Data
{
[XmlElement("Value")]
public ST_Value value = new ST_Value();
[XmlAttribute("name")]
public string csName = "Name";
[XmlAttribute("access")]
public string csAccess = "public";
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string xsi_xmlType = "array";
[XmlAttribute("type")]
public string csType = "NA";
[XmlAttribute("size")]
public string csSize = "-1";
}
public class ST_Field
{
[XmlElement("Value")]
public ST_Value csValue = new ST_Value();
[XmlAttribute("name")]
public string csName = "Name of Type";
[XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string xsi_xmlType = "array"; //always array
[XmlAttribute("type")]
public string csType = "NA";
[XmlAttribute("size")]
public string csSize = "1";
}
public class ST_Value
{
[XmlArrayItem(ElementName = "Field")]
public ST_Field[] csDatas = null;
[XmlAttribute(AttributeName = "key")]
public int csKey = -1;
[XmlAttribute(AttributeName = "link")]
public string csLink = "NA";
}
private ST_DtxInstance DeserializeDTX(string xmlPath)
{
DisplayFile(xmlPath);
XmlSerializer serializer = new XmlSerializer(typeof(ST_DtxInstance));
var fileReader = new FileStream(xmlPath, FileMode.Open);
var result = (ST_DtxInstance)serializer.Deserialize(fileReader);
fileReader.Close();
return result;
}
private void SerializeDTX(ST_DtxInstance instance, string xmlPath)
{
XmlSerializer serializer = new XmlSerializer(typeof(ST_DtxInstance));
TextWriter fileWriter = new StreamWriter(xmlPath);
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
serializer.Serialize(fileWriter, instance, ns);
fileWriter.Close();
DisplayFile(xmlPath);
}
private void DisplayFile(string path)
{
labl.Content = File.ReadAllText(path);
}
And this is the XML-format want to read and write
<Database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.staubli.com/robotics/VAL3/Data/2">
<Datas>
<Data name="Nodes" access="public" **xsi:type="array"** type="Node" size="100">
<Value key="0">
<Field name="Id" **xsi:type="array"** type="num" size="1">
<Value key="0" value="15" />
</Field>
<Field name="Lock" xsi:type="array" type="string" size="1">
<Value key="0" value="NO " />
</Field>
<Field name="Name" xsi:type="array" type="string" size="1">
<Value key="0" value="BasePosition" />
</Field>
<Field name="EdgeInstance" xsi:type="array" type="Edge" size="2">
<Value key="0">
<Field name="CurrentSequencnumber" xsi:type="array" type="num" size="1">
<Value key="0" value="13" />
</Field>
<Field name="CurrentWeight" xsi:type="array" type="num" size="1">
<Value key="0" value="90000" />
</Field>
<Field name="IdEnd" xsi:type="array" type="num" size="1" />
<Field name="IdStart" xsi:type="array" type="num" size="1" />
<Field name="Lenght" xsi:type="array" type="num" size="1" />
<Field name="SpeedLimit" xsi:type="array" type="num" size="1">
<Value key="0" value="30" />
</Field>
</Value>
<Value key="1">
<Field name="CurrentSequencnumber" xsi:type="array" type="num" size="1" />
<Field name="CurrentWeight" xsi:type="array" type="num" size="1" />
<Field name="IdEnd" xsi:type="array" type="num" size="1" />
<Field name="IdStart" xsi:type="array" type="num" size="1" />
<Field name="Lenght" xsi:type="array" type="num" size="1" />
<Field name="SpeedLimit" xsi:type="array" type="num" size="1" />
</Value>
</Field>
</Value>
<Value key="1">
<Field name="Id" xsi:type="array" type="num" size="1" />
<Field name="Lock" xsi:type="array" type="string" size="1" />
<Field name="Name" xsi:type="array" type="string" size="1" />
<Field name="EdgeInstance" xsi:type="array" type="Edge" size="2">
<Value key="0">
<Field name="CurrentSequencnumber" xsi:type="array" type="num" size="1" />
<Field name="CurrentWeight" xsi:type="array" type="num" size="1" />
<Field name="IdEnd" xsi:type="array" type="num" size="1" />
<Field name="IdStart" xsi:type="array" type="num" size="1" />
<Field name="Lenght" xsi:type="array" type="num" size="1" />
<Field name="SpeedLimit" xsi:type="array" type="num" size="1" />
</Value>
<Value key="1">
<Field name="CurrentSequencnumber" xsi:type="array" type="num" size="1" />
<Field name="CurrentWeight" xsi:type="array" type="num" size="1" />
<Field name="IdEnd" xsi:type="array" type="num" size="1" />
<Field name="IdStart" xsi:type="array" type="num" size="1" />
<Field name="Lenght" xsi:type="array" type="num" size="1" />
<Field name="SpeedLimit" xsi:type="array" type="num" size="1" />
</Value>
</Field>
</Value>
</Data>
</Datas>
</Database>
Also, occasionally there might also be an xsi:type="collection" instead of an "array" on some elements within the same array.
I got it working by serializing data and getting serialize output to match input
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication23
{
class Program
{
const string INPUT_FILENAME = @"c:\temp\test.xml";
const string OUTPUT_FILENAME = @"c:\temp\test1.xml";
static void Main(string[] args)
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "http://www.staubli.com/robotics/VAL3/Data/2");
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlReader reader = XmlReader.Create(INPUT_FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Database));
Database database = (Database)serializer.Deserialize(reader);
Database database1 = new Database();
database1.data = new List<Data>();
array data = new array();
database1.data.Add(data);
data.name = "Nodes";
data.access = "public";
data.type = "Node";
data.size = 100;
data.values = new List<Value>();
Value value = new Value();
data.values.Add(value);
value.fields = new List<Data>();
array array1 = new array();
value.fields.Add(array1);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME, settings);
serializer.Serialize(writer, database1, ns);
}
}
[XmlRoot(ElementName = "Database", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
public class Database
{
[XmlArray(ElementName = "Datas", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
[XmlArrayItem(ElementName = "Data", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
public List<Data> data { get; set; }
}
[XmlInclude(typeof(array))]
public class Data
{
[XmlAttribute]
public string name { get; set; }
[XmlAttribute]
public string access { get; set; }
[XmlAttribute]
public string type { get; set; }
[XmlAttribute]
public int size { get; set; }
}
[XmlRoot(ElementName = "array", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
public class array : Data
{
[XmlElement(ElementName = "Value", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
public List<Value> values { get; set; }
}
public class Value
{
[XmlAttribute]
public int key { get; set; }
[XmlElement(ElementName = "Field", Namespace = "http://www.staubli.com/robotics/VAL3/Data/2")]
public List<Data> fields { get; set; }
}
}