2

I have here a variable string named OutputKSZ, containing the code of a XML file. The code of this XML file will contain variable amounts of the tag <streetName language = "EN"> followed by a totally variable street name, and then </streetName>.

Now, I also have a winforms tiny application, with one textbox, one button and one combobox. In the textbox, I copypaste the XML code. Then I click the button, and the combobox should give me a list of all the different street names between each <streetName language = "EN"></streetName> tag.

So, for all clarity, there's two variable things here:

  1. the amount of occurrences of the tag streetName
  2. the length of each string between each streetName tag.

This is what I've tried so far:

if (OutputKSZ.Contains("<address source=\""))
{
    // LIJST MET START INDEXES
    List<int> indexesStart = new List<int>();
    var AddressSourceStart = new Regex("<streetName language=\"EN\">");
    foreach (Match match in AddressSourceStart.Matches(OutputKSZ))
    { indexesStart.Add(match.Index); }

    // LIJST MET END INDEXES
    List<int> indexesEnd = new List<int>();
    var AddressSourceEnd = new Regex("</streetName>");
    foreach (Match match in AddressSourceEnd.Matches(OutputKSZ))
    { indexesEnd.Add(match.Index); }

    int[] counterI = Enumerable.Range(0, indexesStart.Count).ToArray();
    foreach (int i in counterI)
    {
        int KSZGedeelteStraatStart = indexesStart[i];
        int KSZGedeelteStraatEnd = indexesEnd[i];
        int KSZGedeelteStraatLength = KSZGedeelteStraatEnd - KSZGedeelteStraatStart - 26;
        string KSZGedeelteStraat = OutputKSZ.Substring(KSZGedeelteStraatStart + 26, KSZGedeelteStraatLength);
        foreach (int ListCounter in counterI)
        {
            List<string> ListKSZGedeelteStraat = new List<string>();
            ListKSZGedeelteStraat.Add(KSZGedeelteStraat);
            comboBox2.DataSource = ListKSZGedeelteStraat;
        }

    }

Sorry for the Dutch in there. ;)
The problem with this code is that it only displays the very last occurrence, and I'm really fresh out of ideas, I've been at this for hours.

Have you guys any ideas on how to correct this? I'm rather new to c# so as long as I get to keep the textbox, button and combobox, you can rewrite my whole code if need be.

Sample XML:

<soapenv:Envelope>
  <s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" />
  <soapenv:Body>
    <external:searchPersonInformationHistoryBySsinResponse>
      <informationCustomer>
        <customerIdentification>
          <sector>15</sector>
          <institution>5</institution>
        </customerIdentification>
      </informationCustomer>
      <informationCBSS>
        <ticketCBSS>b2d07603-2205-4258-b3b9-49320ab4b919</ticketCBSS>
        <timestampReceive>2016-03-27T12:49:59.680Z</timestampReceive>
        <timestampReply>2016-03-27T12:50:00.072Z</timestampReply>
      </informationCBSS>
      <legalContext>NISSE:IDENTIFICATION</legalContext>
      <criteria>
        <ssin>somenumber</ssin>
        <datagroups>
          <addresses>true</addresses>
        </datagroups>
      </criteria>
      <status>
        <value>DATA_FOUND</value>
        <code>MSG00000</code>
        <description>Successful</description>
      </status>
      <result>
        <person register="RR">
          <ssin>somenumber</ssin>
          <addresses status="DATA_FOUND">
            <address source="NR">
              <residentialAddress>
                <countryCode>150</countryCode>
                <countryName language="FR">Belgique</countryName>
                <countryName language="NL">België</countryName>
                <countryName language="DE">Belgien</countryName>
                <cityCode>somecitycode</cityCode>
                <cityName language="NL">somecityname</cityName>
                <postalCode>somepostalcode</postalCode>
                <streetCode>somestreetcode</streetCode>
                <streetName language="NL">somestreetname</streetName>
                <houseNumber>2</houseNumber>
                <inceptionDate>2014-08-09</inceptionDate>
              </residentialAddress>
            </address>
            <address source="NR">
              <residentialAddress>
                <countryCode>150</countryCode>
                <countryName language="FR">Belgique</countryName>
                <countryName language="NL">België</countryName>
                <countryName language="DE">Belgien</countryName>
                <cityCode>someothercitycode</cityCode>
                <cityName language="NL">someothercityname</cityName>
                <postalCode>someotherpostalcode</postalCode>
                <streetCode>someotherstreetcode</streetCode>
                <streetName language="NL">someotherstreetname</streetName>
                <houseNumber>2</houseNumber>
                <inceptionDate>2014-08-09</inceptionDate>
              </residentialAddress>
            </address>
          </addresses>
        </person>
      </result>
    </external:searchPersonInformationHistoryBySsinResponse>
  </soapenv:Body>
</soapenv:Envelope>

4 Answers4

2

If there is no reason to not parse the XML I'd load it to an XDocument and use a basic LINQ query like this:

var OutputKSZ = textBox1.Text;

var xdocument = XDocument.Parse(OutputKSZ);

var streets = xdocument.Descendants("streetName");

var streetNames = streets.Select(s => s.Value).ToList();

comboBox2.DataSource = streetNames;

This won't work if the data is not a valid xml though.

Petr Vávro
  • 1,506
  • 1
  • 10
  • 12
1

Your loop interation is a bit off.

Try this (included some test data, remove at your convenience).

string OutputKSZ = "<address source=\">" +
                                "<streetName language=\"EN\">1</streetName> " +
                                "<streetName language=\"EN\">12</streetName> " +
                                "<streetName language=\"EN\">111</streetName> "
                                ;

            //Moved for scoping purposes
            List<string> ListKSZGedeelteStraat = new List<string>();

            if (OutputKSZ.Contains("<address source=\""))
            {
                // LIJST MET START INDEXES
                List<int> indexesStart = new List<int>();
                var AddressSourceStart = new Regex("<streetName language=\"EN\">");
                foreach (Match match in AddressSourceStart.Matches(OutputKSZ))
                {
                    indexesStart.Add(match.Index);
                }

                // LIJST MET END INDEXES
                List<int> indexesEnd = new List<int>();
                var AddressSourceEnd = new Regex("</streetName>");
                foreach (Match match in AddressSourceEnd.Matches(OutputKSZ))
                {
                    indexesEnd.Add(match.Index);
                }

                int[] counterI = Enumerable.Range(0, indexesStart.Count).ToArray();
                foreach (int i in counterI)
                {
                    int KSZGedeelteStraatStart = indexesStart[i];
                    int KSZGedeelteStraatEnd = indexesEnd[i];
                    int KSZGedeelteStraatLength = KSZGedeelteStraatEnd - KSZGedeelteStraatStart - 26;
                    string KSZGedeelteStraat = OutputKSZ.Substring(KSZGedeelteStraatStart + 26, KSZGedeelteStraatLength);

                    //Remove additional foreach loop - you were adding too many times
                    ListKSZGedeelteStraat.Add(KSZGedeelteStraat);
                }

                //Assign data source once
                comboBox2.DataSource = ListKSZGedeelteStraat;
            }
Kiel
  • 408
  • 4
  • 13
0

This is a nice way to get what you need using LINQ. Plug this into LinqPad to try it out:

void Main()
{
    XElement contacts =
    new XElement("Contacts",
    new XElement("Contact",
        new XElement("Name", "Patrick Hines"),
        new XElement("Address",
            new XElement("streetName", "Linden Strass",
                new XAttribute("language", "EN")),
            new XElement("City", "Mercer Island"),
            new XElement("State", "WA"),
            new XElement("Postal", "68042")
        )
    ),
        new XElement("Contact",
        new XElement("Name", "Max Dane"),
        new XElement("Address",
            new XElement("streetName", "Marten Strass",
                new XAttribute("language", "EN")),
            new XElement("City", "Mercer Island"),
            new XElement("State", "WA"),
            new XElement("Postal", "68042")
        )
    )
    );

    var streets = contacts.Elements("Contact").Elements("Address").Elements("streetName")
                          .Where(c => (string)c.Attribute("language") == "EN").ToList();

    streets.Dump();

    // Another way to express this getting all elements of that name
    var streets2 = contacts.Descendants("streetName")
                      .Where(c => (string)c.Attribute("language") == "EN").ToList();

    streets2.Dump();
}
0

I would try a different approach with RegEx and Matches. The problem is that maybe it is not the most elegant solution.

I did some research and I found this. There it is explained how to retrieve a string between two known tags.

Here is the function to retrieve the Street names:

List<string> extractString(string xmldata){
    Regex regex = new Regex("<streetName language = \"EN\">(.*?)</streetName>");
    MatchCollection streetCollection = regex.Matches(xmldata);

    //Total number of matches=streetCollection.count
    List<string> streetList = new List<string>();
    for(int i=0;i<streetCollection.count;i++){
        streetList.Add(streetCollection[ctr].Value);
    }

    return streetList;
}

I think it would be something like this. Im not completely sure about the grammar, since Im not in my developing computer, so I have had no chance to check the code myself. But this could be a start. Tell me if you get any errors or something.

Community
  • 1
  • 1