1

I have the following code for the method XmlToDictionary. But how to give input from a button, so that the XML data will be converted to Dictionary

XML Input

<messageTags>
  <tag key="35" value="U1" />
  <tag key="49" value="GEMI1" />
  <tag key="8" value="FIX.4.1" />
  <tag key="9" value="732" />
<messageTags/>

I want the output as below

35=U149=GEMI18=FIX.4.19=732

Code of XmlToDictionary()

public static Dictionary<string, string> XmlToDictionary(string key, string value, XElement baseElm)
{
    Dictionary<string, string> dict = new Dictionary<string, string>();

    foreach (XElement elm in baseElm.Elements())
    {
        string dictKey = elm.Attribute(key).Value;
        string dictVal = elm.Attribute(value).Value;
        dict.Add(dictKey, dictVal);
    }

    return dict;
}

Code for button click()

private void button2_Click(object sender, EventArgs e)
{
    XElement xs = new XElement("messageTags", "tag");
    XmlToDictionary("23", "EUI", xs);
    richTextBox4.Text = XmlToDictionary("messageTags","tag",xs).ToString();                       
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Bikash
  • 17
  • 3
  • 1
    Have you actually checked that your input is as you say? You're creating a single XML element and passing it to your function. You aren't passing the whole structure. – mason Feb 07 '17 at 13:21
  • Even if you have the dictionary, you can't just use `ToString()` to convert it to a FIX format. *Your code* has to construct the string. In fact, you don't need that dictionary at all – Panagiotis Kanavos Feb 07 '17 at 13:51
  • Possible duplicate of [C# XML data into dictionary](http://stackoverflow.com/questions/11994369/c-sharp-xml-data-into-dictionary) – Manfred Radlwimmer Feb 07 '17 at 14:11

3 Answers3

1

Try this...

Following code will give you a dictionary object with all values in XML

 private static void ReadXML2()
    {
        string sXML = "<messageTags>"+
                      "<tag key=\"35\" value=\"U1\" />"+
                      "<tag key=\"49\" value=\"GEMI1\" />"+
                      "<tag key=\"8\" value=\"FIX.4.1\" />"+
                      "<tag key=\"9\" value=\"732\" />"+
                    "</messageTags>";

        XDocument doc = XDocument.Parse(sXML);
        var v = (from p in doc.Descendants("tag")
                 select p).ToDictionary(item => item.Attribute("key").Value,item=> item.Attribute("value").Value);
        Console.WriteLine(v.Count());

    }

Once the dictionary object is created, you can use your method to find a particular key/ value..

By the way your XML string is wrong. You don't have a closing tag for messagetags

UPDATE Use following code which needs no Dictionary object

 var v2 = (from p in doc.Descendants("tag")
                 select p);

        string sOutput = "";
        foreach (var item in v2)
        {
            sOutput += item.Attribute("key").Value + "=" + item.Attribute("value").Value;
        }

        Console.WriteLine(sOutput);

The output is

35=U149=GEMI18=FIX.4.19=732

A3006
  • 1,051
  • 1
  • 11
  • 28
  • Note that the OP asks for a FIX string that can be constructed from the parsed `doc` directly. Even with a valid dictionary the OP won't be able to get the string with `Dictionary.ToString()` – Panagiotis Kanavos Feb 07 '17 at 13:52
  • 1
    You should use a string builder, not concatenate strings. See [String Concatenation Vs String Builder Append](http://stackoverflow.com/questions/1972983/string-concatenation-vs-string-builder-append). – mason Feb 07 '17 at 14:28
1

Your real problem is that you want to generate a FIX message. You tried to do this by generating a dictionary (why?) and then calling ToString() on it. This won't work, because the default implementation of ToString() is to type the object's name.

You don't need to go through the dictionary at all, just parse the XML fragment and generate the final string from the tags. A quick and dirty attempt:

string fragment = "<messageTags>" +
                "<tag key=\"35\" value=\"U1\" />" +
                "<tag key=\"49\" value=\"GEMI1\" />" +
                "<tag key=\"8\" value=\"FIX.4.1\" />" +
                "<tag key=\"9\" value=\"732\" />" +
            "</messageTags>";

var doc = XDocument.Parse(fragment);
var tags = from tag in doc.Descendants("tag")
           select String.Format("{0}={1}",
                                tag.Attribute("key").Value, 
                                tag.Attribute("value").Value);
var message = String.Join("",tags);
Console.WriteLine(message);

Will return 35=U149=GEMI18=FIX.4.19=732

This attempt is dirty because it generates temporary strings, one for each tag pair. FIX is used in high throughput environments which means that performance matters.

A better approach would be to use a StringBuilder and a loop:

var doc = XDocument.Parse(fragment);    
var builder = new StringBuilder();
foreach(var tag in doc.Descendants("tag"))
{
    builder.AppendFormat("{0}={1}", 
                         tag.Attribute("key").Value, 
                         tag.Attribute("value").Value);
};
var message = builder.ToString();
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
0

See my version below.. keeping it as a callable method.

UPDATED

did it as you wanted but... i think there is an error in your request... look closely at '35=U149=GEMI18=FIX.4.19=732' how is what ever is doing to consume this gona know that GEMI18 is actaually GEMI1 [space] 8

  public static void DoStuff()
    {
        var stringXml = @"<messageTags> 
                                <tag key=""35"" value=""U1"" />
                                <tag key=""49"" value=""GEMI1"" />
                                <tag key=""8"" value=""FIX.4.1"" />
                                <tag key=""9"" value=""732"" />
                       </messageTags>";

        XmlDocument xmltest = new XmlDocument();
        xmltest.LoadXml(stringXml);

        XmlNodeList elemlist = xmltest.GetElementsByTagName("messageTags");

        var dic = XmlNodeListToDictionaryByAttribute("key", "value", elemlist);
        var test = DictToString(dic, "{0}={1}");
    }

    public static Dictionary<string, string> XmlNodeListToDictionaryByAttribute(string keyAttribute, string valueAttribute, XmlNodeList elemlist)
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();

        foreach (XmlNode item in elemlist)
        {
            foreach (XmlNode childNode in item.ChildNodes)
            {
                var dictKey = childNode.Attributes[keyAttribute].Value;
                var dictVal = childNode.Attributes[valueAttribute].Value;
                dict.Add(dictKey, dictVal);
            }
        }
        return dict;
    }


    public static string DictToString<T>(IDictionary<string, T> items, string format)
    {
        format = String.IsNullOrEmpty(format) ? "{0}='{1}' " : format;

        StringBuilder itemString = new StringBuilder();
        foreach (var item in items)
            itemString.AppendFormat(format, item.Key, item.Value);

        return itemString.ToString();
    }
Seabizkit
  • 2,417
  • 2
  • 15
  • 32
  • The dictionary isn't really necessary. You can go from the XML to the FIX format without the dictionary, and make the code much cleaner. – mason Feb 07 '17 at 14:29