0

Hey Everyone have a question here about parsing some XML in C# .net 4 MVC 3.

I have a Map (HashMap) that is serialized to XML from a java app.

I need to parse this into an object on the dotnet side but can't seem to figure it out. In my research I see you can't serialize into Dictionary<string, string>.

Someone else suggested a public struct KeyValuePair<K, V> but that didn't seem to work.

Also tried an [XmlArray("mapConfig")]

One of the prerequisites is we have to use System.Xml.Serialization because we have an abstract messenger class and I would like to avoid changing that if I don't absolutely have to.

If I have to I could possiblly change the Java object if that would make this easier but would rather use the one already there if possible. If it helps the Java layer is using Xstream.

Here is a chunk of XML that is being sent from Java

<ConfigurationMap>
    <mapConfig class="hashtable">
      <entry>
        <string>Key1</string>
        <string>Value1</string>
      </entry>
      <entry>
        <string>Key2</string>
        <string>Value2</string>
      </entry>
      <entry>
        <string>Key3</string>
        <string>Value3</string>
      </entry>
      <entry>
        <string>Key4</string>
        <string>Value4</string>
      </entry>
    </mapConfig>
</ConfigurationMap>

Thanks, please let me know if you need more information. Look forward to the answers.

--UPDATE--

I thought it was apparent but I should've mentioned that the XML is coming back in the abstract message I mentioned in the form of a string. The current method uses:

XmlDocument doc = new XmlDocument();
doc.LoadXml(this.ResponseXml);
XmlElement main = doc.DocumentElement;

XmlElement cse = util.getElementsFirstChild(main, "MessagePayload");
XmlElement ccs = util.getElementsFirstChild(cse, "ReturnedObjectNameHERE");

We then deserialize the fragment using the System.Xml attributes on the model.

Here is a simple example of a Model we use with some generic properties :

[XmlRoot("list")]
public class SearchResults : List<CSearchResult>
{
    public SearchResults() { }
}

[XmlRoot("SearchResult")]
public class SearchResult
{
    [XmlElement("Id")]
    public string OrgUnitId { get; set; }

    [XmlElement("Type")]
    public Type Type { get; set; }

    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlElement("Description")]
    public string Description { get; set; }
}

-- UPDATE 2 -- I was able to get some decent model binding using this model class below

[XmlRoot("ConfigurationMap")]
public class ConfigurationMap
{
    [XmlElement("mapConfig")]
    public MapConfig mapConfig { get; set; }

}

[XmlRoot("mapConfig")]
public class MapConfig
{
    [XmlArray("entry")]
    public List<string> entry { get; set; }
}

Only problem with this is the Object property mapconfig just bunches all of the entries together in one list, which makes sense given the model.

Trying to mess around with the array types to see if I can get a better result. Looking at making MapConfig an array of Entry. The I can either keep Entry a list or make Entry an array to so the object structure becomes:

MapConfig: [[key1, value1], [key2, value2], [key3, value3], [key4, value4],]

Trying to decide if this is a better structure to work with or not.

Any advice on this would be helpful as I work through this.

Thanks

PJH
  • 497
  • 4
  • 12
  • 3
    This simple structure you could easily parse manually using XmlReader. – Alxandr Mar 06 '13 at 17:24
  • [XmlReader Class](http://msdn.microsoft.com/en-us/library/system.xml.xmlreader(v=vs.71).aspx); – Brian Mar 06 '13 at 17:28
  • This seems like homework, so I adjusted the tags as the OP says, `"we have to use"` Removed the tag java, as there is nothing in the question that relates to programming in java. – Chuck Savage Mar 06 '13 at 18:46
  • This is not homework and the prereqs are there because a framework is already in place. – PJH Mar 06 '13 at 20:04
  • XmlReader class will not help because it requires an XML uri parameter. As mentioned in the post an abstract messenger object is used to deserialize the object from response, which is an XML string. Would like to know how to deserialize the string above without having to write some custom code but if it is necessary I will entertain the idea. – PJH Mar 06 '13 at 20:05
  • It does relate to java because if you read the post it is coming from a serialized HashMap from Java. I even ask the posters if they suggest something different on the Java layer that would make the translation into a c# object more intuitive. There doesn't seem to be a good way to send key value pairs between the two. You obviously did not read the post and you modifying my tags and suggesting this is homework is rude. Perhaps I did not fully explain the circumstance and that is on me. I have added more information to the orig post. – PJH Mar 06 '13 at 20:34
  • 3
    @ChuckSavage The [tag:homework] tag is deprecated and shouldn't be used anymore. Consider questions on their merit, not on their motivation. – millimoose Mar 06 '13 at 20:47
  • 1
    Also, your requirement is likely to make things more difficult than not. Java's XML serialisation and .NET's XML serialisation were not meant to interoperate or to conveniently handle mapping data structures to/from arbitrary XML, it seems counterproductive to try to force them to instead of using the right tool for the job. – millimoose Mar 06 '13 at 20:49
  • +1 millimoose couldn't agree more. Unfortunately I am currently handcuffed using my companies framework. I am pushing for switching to something else. I have read about json and gson playing nice together between the two and also allows for serialization of dictionary types between. I haven't gotten around to constructing a prototype for a more universal way. In the meantime have to do it this way. – PJH Mar 06 '13 at 21:06

2 Answers2

2

You could create a class to serialize into... So run xsd.exe on the xml...

C:\>xsd test.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.17929]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\test.xsd'.

C:\>xsd test.xsd /classes
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.0.30319.17929]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\test.cs'.

then just use the simple c# XmlSerializer...

NewClassName object = xml.DeSerializeStringToObject<NewClassName>();

Helper Class below

public static class XmlSerializerHelper
{
    public static T DeSerializeStringToObject<T>(this string sxml)
    {
        using (XmlTextReader xreader = new XmlTextReader(new StringReader(sxml.Replace("&", "&amp;"))))
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            return (T)xs.Deserialize(xreader);
        }
    }

    public static string SerializeObjectToString(this object obj)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            XmlSerializer x = new XmlSerializer(obj.GetType());
            x.Serialize(stream, obj);
            return Encoding.Default.GetString(stream.ToArray());
        }
    }
}

Of course the the first string in the array will be the key.

retslig
  • 888
  • 5
  • 22
  • +1 for actually providing a constructive answer. Thank you. I am looking into this and trying out different ways to deserialize this. Unfortunately it doesn't look like there is a good built in attribute and model structure to account for this from what I have read. Outside of creating a custom dictionary serialization object. – PJH Mar 06 '13 at 20:30
  • So I was messing around with xsd for awhile yesterday and it kept creating classes that were unserializable with the given xml. Snooped around a bit and found out there is a bug in xsd when it tries to create and array of arrays from XML. You can see it here. This has given me some leads on some different types of model binding to try. Here is a link to the bug: http://stackoverflow.com/questions/2188930/net-xsd-importer-creates-unserializable-class – PJH Mar 07 '13 at 14:45
0

The solution seemed to be simpler than I imagined but really was depended upon selecting the right combination of model attributes to parse correctly.

Here is the one I decided to use as it divides each entry up into its own list item.

[XmlRoot("ConfigurationMap")]
public class ConfigurationMap
{
    [XmlArray("mapConfig")]
    [XmlArrayItem("entry")]
    public List<Entry> MapConfig { get; set; }

}

[XmlRoot("entry")]
public class Entry
{
    [XmlElement("string")]
    public List<string> entry { get; set; }
}

Hopefully this helps out someone else. Thanks for the input everyone.

PJH
  • 497
  • 4
  • 12