1

I am struggling to serialize the following XML code...

<Activity mc:Ignorable="sap sap2010 sads" x:Class="Main"
 xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:sco="clr-namespace:System.Collections.ObjectModel;assembly=mscorlib"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextExpression.NamespacesForImplementation>
    <sco:Collection x:TypeArguments="x:String">
      <x:String>System.Activities</x:String>
      <x:String>System.Activities.Statements</x:String>
      <x:String>System.Activities.Expressions</x:String>
      <x:String>System.Activities.Validation</x:String>
      <x:String>System.Activities.XamlIntegration</x:String>
      <x:String>Microsoft.VisualBasic</x:String>
      <x:String>Microsoft.VisualBasic.Activities</x:String>
      <x:String>System</x:String>
      <x:String>System.Collections</x:String>
      <x:String>System.Collections.Generic</x:String>
      <x:String>System.Data</x:String>
      <x:String>System.Diagnostics</x:String>
      <x:String>System.Drawing</x:String>
      <x:String>System.IO</x:String>
      <x:String>System.Linq</x:String>
      <x:String>System.Net.Mail</x:String>
      <x:String>System.Xml</x:String>
      <x:String>System.Xml.Linq</x:String>
      <x:String>UiPath.Core</x:String>
      <x:String>System.Windows.Markup</x:String>
      <x:String>UiPath.Core.Activities</x:String>
    </sco:Collection>
  </TextExpression.NamespacesForImplementation>
</Activity>

I feel I have tried all combinations of [XmlArray] and [XmlArrayItem] on various properties but I can's seem to capture both the TypeArguments attribute and the list of string values. I am also unsure on which classes I need to produce to make this work. Any suggestions?

Note I have also tried using the 'Special Paste' option to generate the class structure, but after serializing and immediately deserializing, the output xml file is not of the same structure.

  • 1
    Do you have Visual Studio 2012+? If so, try method 2 from [this answer](https://stackoverflow.com/a/19613934/4416750). If not, try method 1 :) – Lews Therin Jan 28 '19 at 21:58
  • @LewsTherin I do and I have tried this too. Seems to completely ignore this part of the XML file for some reason! I have therefore been forced to attempt it manually. – unknownpresense Jan 28 '19 at 22:00
  • Did you run the XML through an XML validator? If the XML is invalid those two methods won't work properly. – Lews Therin Jan 28 '19 at 22:05
  • Can you show more of your xml (say with the namespaces, and make it valid XML)? That way, we could try to repro your issue. – Flydog57 Jan 28 '19 at 22:31
  • @Flydog57 Sure thing. I will add it to the original post. I have also validated this to be valid xml. – unknownpresense Jan 28 '19 at 23:07
  • Well, I thought I knew how to do it, but I've spent too much time at it so I'm giving up. What I did was make a `Collection` class that implemented `IList` and that, for good measure, had an indexed property (`public string this[int i]`). It also had a string property named `TypeArguments`. That allowed me to put a `XmlArray` and `XmlArrayItem` attributes on the `Collection` member of my `TextExpressionNamespacesForImplementation` class. It deserializes without error, but it doesn't populate my `Collection` instance. I hope that there's some hints in here that help you – Flydog57 Jan 29 '19 at 00:52
  • @Flydog57 Haha I thought the same thing to begin with too! Spent a few evenings on it but still got no where, hence my post :) Solution in chosen answer worked for me perfectly! – unknownpresense Jan 29 '19 at 23:47

1 Answers1

2

The following works for me.

Classes used for serializing and deserializing:

[XmlRoot(Namespace = "http://schemas.microsoft.com/netfx/2009/xaml/activities")]
public class Activity
{
    [XmlAttribute(Namespace = "http://schemas.microsoft.com/netfx/2009/xaml/activities")]
    public string Ignorable { get; set; }

    [XmlAttribute(Namespace = "http://schemas.microsoft.com/winfx/2006/xaml")]
    public string Class { get; set; }

    [XmlElement("TextExpression.NamespacesForImplementation")]
    public NamespacesForImplementation NamespacesForImplementation { get; set; }
}

public class NamespacesForImplementation
{
    [XmlElement(Namespace = "clr-namespace:System.Collections.ObjectModel;assembly=mscorlib")]
    public NamespaceCollection Collection { get; set; }
}

public class NamespaceCollection
{
    [XmlAttribute(Namespace = "http://schemas.microsoft.com/winfx/2006/xaml")]
    public string TypeArguments { get; set; }

    [XmlElement(ElementName = "String", Namespace = "http://schemas.microsoft.com/winfx/2006/xaml")]
    public List<string> Content { get; set; }
}

Test program serializing the exact XML in your question:

class Program
{
    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Activity));

        Activity activity;
        using (var stream = File.OpenText("Test.xml"))
        {
            activity = (Activity) serializer.Deserialize(stream);
        }

        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add(string.Empty, "http://schemas.microsoft.com/netfx/2009/xaml/activities");
        ns.Add("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
        ns.Add("sco", "clr-namespace:System.Collections.ObjectModel;assembly=mscorlib");
        ns.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

        using (var stringWriter = new StringWriter())
        {
            serializer.Serialize(stringWriter, activity, ns);
            Console.WriteLine(stringWriter.ToString());
        }
    }
}

The output of the program is the following:

<?xml version="1.0" encoding="utf-16"?>
<Activity xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sco="clr-namespace:System.Collections.ObjectModel;assembly=mscorlib" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="Main" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities">
  <TextExpression.NamespacesForImplementation>
    <sco:Collection x:TypeArguments="x:String">
      <x:String>System.Activities</x:String>
      <x:String>System.Activities.Statements</x:String>
      <x:String>System.Activities.Expressions</x:String>
      <x:String>System.Activities.Validation</x:String>
      <x:String>System.Activities.XamlIntegration</x:String>
      <x:String>Microsoft.VisualBasic</x:String>
      <x:String>Microsoft.VisualBasic.Activities</x:String>
      <x:String>System</x:String>
      <x:String>System.Collections</x:String>
      <x:String>System.Collections.Generic</x:String>
      <x:String>System.Data</x:String>
      <x:String>System.Diagnostics</x:String>
      <x:String>System.Drawing</x:String>
      <x:String>System.IO</x:String>
      <x:String>System.Linq</x:String>
      <x:String>System.Net.Mail</x:String>
      <x:String>System.Xml</x:String>
      <x:String>System.Xml.Linq</x:String>
      <x:String>UiPath.Core</x:String>
      <x:String>System.Windows.Markup</x:String>
      <x:String>UiPath.Core.Activities</x:String>
    </sco:Collection>
  </TextExpression.NamespacesForImplementation>
</Activity>
Szabolcs Dézsi
  • 8,743
  • 21
  • 29
  • 1
    Thank you very much, this worked for me :D This also allowed me to identify my error: I kept trying to use `[XmlArray]` or `[XmlArrayItem]` on the `List` instead of `[XmlElement]`. – unknownpresense Jan 29 '19 at 23:51
  • 2
    Very slick. I wondered down the same path as @unknownpresense, and that leads nowhere. I was about to suggest hand implementing `IXmlSerializable` on the Collection class. This is **so** much better a solution. – Flydog57 Jan 30 '19 at 00:02