0

I am reading xml. From this xml I am storing 4 parameters into array.

How do I combine these arrays into one foreach loop so I can store these data into SQL and work with them?

I managed to create .Zip for two arrays. Is it possible to combine 4 arrays like that? Basically I would like to add id and recDate into numbersAndWords array.

XmlDocument doc = new XmlDocument();

        doc.LoadXml(result);

        var cislo = new List<string>();
        var zprava = new List<string>();
        var id = new List<string>();
        var recDate = new List<string>();

        XmlNodeList number = doc.GetElementsByTagName("SenderNumber");
        for (int i = 0; i < number.Count; i++)
        {
            cislo.Add(number[i].InnerXml);
        }

        XmlNodeList text = doc.GetElementsByTagName("TextDecoded");
        for (int i = 0; i < text.Count; i++)
        {
            zprava.Add(text[i].InnerXml);
        }

        XmlNodeList idNum = doc.GetElementsByTagName("ID");
        for (int i = 0; i < idNum.Count; i++)
        {
            id.Add(idNum[i].InnerXml);
        }

        XmlNodeList recDateTime = doc.GetElementsByTagName("ReceivingDateTime");
        for (int i = 0; i < recDateTime.Count; i++)
        {
            recDate.Add(recDateTime[i].InnerXml);
        }



        var numbersAndWords = cislo.Zip(zprava, (n, w) => new {Number = n, Word = w});
        cs.Open();
        foreach (var nw in numbersAndWords)
        {
            MessageBox.Show(nw.Number);
            MessageBox.Show(nw.Word);
        }
Stewbob
  • 16,759
  • 9
  • 63
  • 107
Cabry
  • 125
  • 12
  • Possible duplicate of [How to combine more than two generic lists in C# Zip?](https://stackoverflow.com/questions/10297124/how-to-combine-more-than-two-generic-lists-in-c-sharp-zip) – Palle Due May 02 '19 at 11:51
  • Since you are constructing 4 lists, why not create 1 list of objects, and update those objects instead? Also, it seems you're parsing the same document, why not deserialize it properly instead and avoid all this hassle? – Lasse V. Karlsen May 02 '19 at 12:19
  • In other words, you've constructed a problem by writing unwieldy code to parse an XML document, and now you're trying to find a good way to handle that problem. Don't, get rid of the problem and use xml deserialization, this would give you 1 list of objects with properties, the exact result you probably want the zips to produce. – Lasse V. Karlsen May 02 '19 at 12:24
  • For instance, does your code handle it if one such object is *missing* one of those properties? Won't the indexes be skewed then? – Lasse V. Karlsen May 02 '19 at 12:25
  • @LasseVågsætherKarlsen I think that it is almost impossible that something can miss from the xml. Atleast it should be impossible. – Cabry May 02 '19 at 12:37
  • Either way, I would just define a proper class hierarchy and do normal deserialization, it will be easier to read, easier to write, easier to maintain, easier to understand, and far less convoluted logic. – Lasse V. Karlsen May 03 '19 at 07:56
  • @LasseVågsætherKarlsen I think that I can't make something like that due to my skill with c#. So, so far I gotta need to deal with my code this way. But thank you for the suggestion. – Cabry May 03 '19 at 08:01

3 Answers3

1

Try combine these arrays using a method like this:

private static T[] Combine<T>(params IEnumerable<T>[] items) =>
                              items.SelectMany(i => i).Distinct().ToArray();

And use it:

var combinedArrays = Combine(cislo, zprava, id, recDate);

for (int i = 0; i < combinedArrays.Length; i++)
{
    MessageBox.Show(i);
    MessageBox.Show(combinedArrays[i]);
}

If you want do execute an sql statement in the, would be nice if you create a new class and fill it with the data. For sample:

public class Item
{
   public string Id { get; set; }
   public string Cislo { get; set; }
   public string Zprava { get; set; }
   public string RecDate { get; set; }
}

var items = id.Select((id, index) => new Item() 
                                       {
                                          Id = id,
                                          Cislo = cislo[index],
                                          Zprava = zprava[index],
                                          RecDate = recDate[index]                                             
                                        }).ToList();

foreach (var item in items)
{
   string sql = " insert into contacts(id, zprava, cislo) values (@id, @zprava, @cislo)";

   var command = new SqlCommand(sql, connection);

   // bind the parameters in the sql based on the `item` object.
   // execute the command, etc..
}
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
  • Nice it combined into one array. Is now possible that to get messagebox for each of the items? I know I could do that without combining arrays like _MessageBox.Show(id[1].toString());_, but I don't know how much items is going to be loaded. What if I want then execute SQL command like this : _insert into contacts(id, zprava, cislo) values ('"+id+"', '"+zprava+"', '"+cislo+"')_ – Cabry May 02 '19 at 12:40
  • 1
    If you want to execute a statement like this it is another question. I will update my answer. – Felipe Oriani May 02 '19 at 13:22
0

If you're sure, that all elements count is equal, create class and fill it:

class Record
{
   public string cislo;
   public string zprava;
   public string id;
   public string recDate;
}
.....
List<Record> records = new List<Record>();
    XmlNodeList number = doc.GetElementsByTagName("SenderNumber");
    for (int i = 0; i < number.Count; i++)
    {
       records.Add(new Record { cislo = number[i].InnerXml });
    }

    XmlNodeList text = doc.GetElementsByTagName("TextDecoded");
    for (int i = 0; i < text.Count; i++)
    {
        records[i].zprava = text[i].InnerXml;
    }

etc

Flutter
  • 93
  • 8
0

You could use an implementation of Zip that zips four enumerables, and returns as a result an enumerable of ValueTuple<T, T, T, T> elements:

public static IEnumerable<(T, T, T, T)> Zip4<T>(IEnumerable<T> source1,
    IEnumerable<T> source2,
    IEnumerable<T> source3,
    IEnumerable<T> source4)
{
    using (IEnumerator<T> e1 = source1.GetEnumerator(),
        e2 = source2.GetEnumerator(),
        e3 = source3.GetEnumerator(),
        e4 = source4.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext())
        {
            yield return (e1.Current, e2.Current, e3.Current, e4.Current);
        }
    }
}

Usage example:

foreach (var combo in Zip4(cislo, zprava, id, recDate))
{
    Console.WriteLine($"{combo.Item1}-{combo.Item2}-{combo.Item3}-{combo.Item4}");
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104