简体   繁体   中英

How can I convert an XML fragment to a Dictionary in C#?

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();                       
}

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

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();

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();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM