Credo che come prima cosa c'è da fare una precisazione nel senso che il SiteMap non è altro che un file XML quindi il controllo menù può essere riempito essenzialmente in due modi o tramite XML(cosa che hai giustamente indicato) oppure andando ad agire sulla collection MenuItemCollection aggiungendo dei MenuItem.
Detto questo di soluzioni alternative nè esistono, per esempio tempo fa mi son costruito un controllo che mi generava un menù il cui markup in fase di renderizzazione non era altro che una serie di div ed elenchi opportunamente formattati.
Avevo scelto questa strada perchè all'epoca non mi era assolutamente piaciuta la gestione dei css per i vari item/menù( credo che adesso con i Css Friendly il controllo si possa customizzare notevolmente e più facilmente ma sinceramente non ho mai provato. Ad ogni modo se ti interessa questo è il link: CSS Friendly Control Adapters - Home).
NB: Inoltre non sò se il controllo in questione è cross browser(dipende se stai realizzando un'applicazione intranet o meno)
Oltre alla soluzione più custom ma sicuramente più "dispendiosa" in termine di tempo dato che devi scrivere molto più codice, c'è la possibilità di usare/provare alcuni controlli menù già pronti(anche questi mai testati...il primo sicuramente free, il secondo non ricordo):
obout inc - obout Text Menu - What is obout Text Menu
Advanced Menu for ASP.NET
Per quanto riguarda l'ultima domanda cioè come dare in pasto un xml al menù, basta usare le classi che il Framework ti mette a disposizione. Giusto per darti un'idea:
XmlDocument doc = new XmlDocument();
XmlNode nodeDeclaration = doc.CreateNode(XmlNodeType.XmlDeclaration, string.Empty, string.Empty);
doc.AppendChild(nodeDeclaration);
XmlNode nodeRoot = doc.CreateNode(XmlNodeType.Element, "Menu", string.Empty);
nodeRoot.InnerText = "Lista";
doc.AppendChild(nodeRoot);
XmlElement elementPadre;
XmlElement elementFiglio;
XmlAttribute attr;
for (int i = 0; i < 5; i++)
{
elementPadre = doc.CreateElement(null, "Categorie", string.Empty);
attr = doc.CreateAttribute("DescCategoria");
attr.Value = "Categoria: " + i.ToString();
elementPadre.Attributes.Append(attr);
attr = doc.CreateAttribute("IdCategoria");
attr.Value = i.ToString();
elementPadre.Attributes.Append(attr);
for (int j = 0; j < 3; j++)
{
elementFiglio = doc.CreateElement(null, "Articoli", string.Empty);
attr = doc.CreateAttribute("DescArticolo");
attr.Value = "Articolo: " + i.ToString() + "." + j.ToString();
elementFiglio.Attributes.Append(attr);
attr = doc.CreateAttribute("IdArticolo");
attr.Value = j.ToString();
elementFiglio.Attributes.Append(attr);
elementPadre.AppendChild(elementFiglio);
}
doc.ChildNodes.Item(1).AppendChild(elementPadre);
}
XmlDataSource xmlDataSource = new XmlDataSource();
xmlDataSource.Data = doc.InnerXml;
Menu1.DataSource = xmlDataSource;
Menu1.DataBind();
mentre il markup:
<asp:Menu ID="Menu1" runat="server" Orientation="vertical">
<DataBindings>
<asp:MenuItemBinding DataMember="Categorie" TextField="DescCategoria" ValueField="IdCategoria" />
<asp:MenuItemBinding DataMember="Articoli" TextField="DescArticolo" ValueField="IdArticolo" />
</DataBindings>
</asp:Menu>