How to Make Things Complicated

I have some classes that work together to make writing html easier.  One class is Element and one Attribute that represent their obvious pieces of html.  One feature implemented is the ability to add attributes as a string like this: border=0;height=100%; .  As a feature, that string is parsed into two attributes, one representing border with a value of 0 and the other representing height with a value of 100%.  Simple, right? Totally. 

Here's the code i was using to parse that string into attributes, the first thing is to split on the semi-colons:


public virtual Element AddAttribute(string nameValuePairsSeparatedByAnEqualsSign)
{
	string[] nameValuePairs = nameValuePairsSeparatedByAnEqualsSign.Split(';');
	foreach (string nameValuePair in nameValuePairs)
	{

		if (String.IsNullOrEmpty(nameValuePair))
			continue;

		this.AddAttribute(new Attribute(nameValuePair));
	}
	return this;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

And here's the contstructor for an Attribute:


public Attribute(string nameValuePairsSeparatedByAnEqualsSign)
{
	if (String.IsNullOrEmpty(nameValuePairsSeparatedByAnEqualsSign))
		throw new ArgumentException("nameValuePairSeparatedByEqualsSign is null or empty.", "nameValuePairsSeparatedByAnEqualsSign");

	string[] nameValues = nameValuePairsSeparatedByAnEqualsSign.Split('=');
	_name = nameValues[0];
	if (nameValues.Length > 1)
		_value = nameValues[1];
}
1
2
3
4
5
6
7
8
9
10

This was all working perfectly until I started a new project, one of the tasks of the project is to create a .csproj file.  One element of a csproj looks like this:


Debug
1

That's perfectly legit xml, but that attribute busted my code, the double equals.  So I set out to fix it.  Here's something I came up with that worked, but man, soooooo stoopid complicated:


public static List Parse1(string attlist)
	{
		List attributes = new List();
		List buffer = new List();

		Pair attribute = null;
		for (int i = 0; i char c = attlist[i];

			if (c == '=')
			{
				if (attlist[i + 1] == '=')
				{
					buffer.Add(c);
					buffer.Add('=');
					i++;
				}
				else
				{
					if (attribute == null)
					{
						attribute = new Pair();
						attribute.First = new String(buffer.ToArray());
					}
					else
					{
						attribute.Second = new String(buffer.ToArray());
						attributes.Add(attribute);
						attribute = null;
					}
					buffer.Clear();
				}
			}
			else if (c == ';')
			{
				attribute.Second = new String(buffer.ToArray());
				attributes.Add(attribute);
				attribute = null;
				buffer.Clear();
			}
			else
				buffer.Add(c);
		}
		if (attribute != null)
		{
			attribute.Second = new String(buffer.ToArray());
			attributes.Add(attribute);
		}
		return attributes;
	}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

I asked Levon Hackmeister how he'd do the same thing, and had a wicked simple solution, replace the double equals with something else like deq, do the original split on equals, then replace deq with the original ==.  Blam, done.  Here's the modified code, just needed to change the constructor on Attribute. Note the Replace("==", "&deq;") before the split on equals, and the Replace("&deq;", "==") when assigning the value.


public Attribute(string nameValuePairsSeparatedByAnEqualsSign)
{
	if (String.IsNullOrEmpty(nameValuePairsSeparatedByAnEqualsSign))
		throw new ArgumentException("nameValuePairSeparatedByEqualsSign is null or empty.", "nameValuePairsSeparatedByAnEqualsSign");

	string[] nameValues = nameValuePairsSeparatedByAnEqualsSign.Replace("==", "&deq;").Split('=');
	_name = nameValues[0];
	if (nameValues.Length > 1)
		_value = nameValues[1].Replace("&deq;", "==");
}
1
2
3
4
5
6
7
8
9
10

Sometimes it's easy to skip over an easy solution and jump right into a pile of crap. 

Regular Expressions

I thought about using regex. That's as far as I got though :)

 
Author: , 0000-00-00