Tuesday, January 29, 2008

Write your own DOM friendly extension methods for HtmlElement in Volta

logo-volta

I know there are GetById, GetById<> methods in Document object. But, I often miss a method that I feel should be in Volta, which iterates through its child nodes and find an element for me. Let us say, there is a HTML like the following:

<div id="divContainer">
<
b>Some text</b>
<
div id="firstDiv">
<
i>Some more text</i>
</
div>
<
div id="secondDiv">
Okay, I gotta go now
</div>
<
div anyAttribute="anyValue">
Babye
</div>
</
div>

The most important thing is, I can not get the last div by Document.GetById, because instead of id I chose anyAttribute. So, I wrote my own extension method which can run into not only Div but also any HtmlElement, and can find me the desired HtmlElement inside the prior one with the anyAttribute and anyValue. To make my intention clear, I'd like to show how I'd like to use that extension method:

var divContainer = Document.GetById<Div>("divContainer");
var anyDiv = divContainer.Find<Div>("anyAttribute", "anyValue");

if(anyDiv != null)
anyDiv.InnerHtml += "guys!";

So, I'd like to call my extension method Find<> which will take the type I'm looking for (in this case a Div) and that HtmlElement should have an attribute "anyAttribute" that contains "anyValue". Here is how I make up the extension method:

public static class HtmlExtensions
{
public static T Find<T>(this T parent, string attribute, string value)
where T : HtmlElement
{
var element = parent.FirstChild;

while(element != null)
if (element.IsProper<T>(attribute, value))
return element as T;
else
element = element.NextSibling;

return null;
}

public static bool IsProper<T>(this DomNode element, string attribute, string value)
where T : HtmlElement
{
if (element.GetType() == typeof(T) &&
element.Attributes != null &&
element.Attributes.GetNamedItem(attribute) != null &&
element.Attributes.GetNamedItem(attribute).Value == value)

return true;

return false;
}
}

This method can iterate only one depth. Multi depth implementation can be done by running a simple DFS which is left to you guys. Note one thing, I have called one extension method "IsProper" inside another extension method, and there is no harm in it. So, this is how you can add your own extension methods to the HtmlElement.

No comments: