A very simple implementation (there are better, more efficient, more robust, ways of doing the task) to get you started if you really cannot use an xml library to search with native xml functionality. Remember to add exception handling and special cases and additional validation where appropriate.
// usage
private static void Main(string[] args) {
Searcher searcher = new Searcher();
foreach (SearchExtract extract in searcher.GetOccurances(System.IO.File.ReadAllText(@"c:\temp\testfile.txt"))) {
//do somethign with extract
}
}
public class SearchExtract {
// makes it easier to find in the document for checking, can even use to calculate lines
public int StartIndex {
get; set;
}
public string ControlDisplayName {
get; set;
}
public string ControlId {
get; set;
}
public string DataFieldName {
get; set;
}
}
// does not check for end of file
public class Searcher {
private const string Start = "<mcwb:Control "; // with the space
private const string End = ">";
// use a stream as input and a stream reader (buffered) for large files
public System.Collections.Generic.IEnumerable<SearchExtract> GetOccurances(string input) {
int position = 0;
int startIndex = input.IndexOf(Start, position, System.StringComparison.Ordinal);
while (startIndex >= 0) {
// first lets try find the end
// assuming the end string is never in a comment or included string literal value, else you need to accomodate for this
int endIndex = input.IndexOf(End, startIndex);
// now the other values
int controlDisplayNameIndex = input.IndexOf(nameof(SearchExtract.ControlDisplayName), startIndex, System.StringComparison.Ordinal);
int controlIdIndex = input.IndexOf(nameof(SearchExtract.ControlId), startIndex, System.StringComparison.Ordinal);
int dataFieldNameIndex = input.IndexOf(nameof(SearchExtract.DataFieldName), startIndex, System.StringComparison.Ordinal);
// now make sure the values are all before the end character
// here the assumption is you need all for it to be a valid search extract
// and that every start has an end .. ie not malformed file in this regard
if (controlDisplayNameIndex < endIndex && controlIdIndex < endIndex && dataFieldNameIndex < endIndex) {
string controlDisplayNameValue = FindValue(controlDisplayNameIndex + nameof(SearchExtract.ControlDisplayName).Length, input);
string controlIdValue = FindValue(controlIdIndex + nameof(SearchExtract.ControlId).Length, input);
string dataFieldNameValue = FindValue(dataFieldNameIndex + nameof(SearchExtract.DataFieldName).Length, input);
// validate
if (controlDisplayNameValue != null && controlIdValue != null && dataFieldNameValue != null) {
// iterate
yield return new SearchExtract() {
StartIndex = startIndex,
ControlDisplayName = controlDisplayNameValue,
ControlId = controlIdValue,
DataFieldName = dataFieldNameValue
};
}
}
startIndex = input.IndexOf(Start, endIndex + 1, System.StringComparison.Ordinal);
}
}
// introduce some additional terminal checks .. such as maximum value length
private string FindValue(int index, string input) {
const string ValueDelimiter = "\"";
string value = null;
int startIndex = input.IndexOf(ValueDelimiter, index, System.StringComparison.Ordinal);
int endIndex = -1;
if (startIndex >= 0) {
endIndex = input.IndexOf(ValueDelimiter, startIndex + 1, System.StringComparison.Ordinal);
}
if (endIndex > 0) {
value = input.Substring(startIndex + 1, endIndex - startIndex - 1);
// do some validation on value
}
return value;
}
}