Home > front end >  XML Deserialization of xsi:type="array"
XML Deserialization of xsi:type="array"

Time:06-28

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.

CodePudding user response:

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; }
    }
  
}
  • Related