Monday, November 08, 2010 at 12:03 AM.

on walk (adroutline, identifier, path, adrcrumblist, adrlastxstruct, adrrulestable, adrOpmlUrl, adrdirectories=nil,, owneremail=user.prefs.mailAddress, adrInSiteInclusionCallback=nil) {
		<<6/5/02; 4:19:22 PM by JES
			<<New optional parameter, adrInSiteInclusionCallback, is the address of a script which dives into an in-site inclusion -- a path-part which begins with the '~' character.
		<<11/6/2000; 12:48:20 PM by DW
			<<Created. adrdiscussiongroup and msgnum specify a message that contains an OPML document.
			<<path is a relative path into the document. We do the walk and return the address of the item it refers to, or scriptError if it doesn't exist.
			<<When looking, we only consider the first word of each item, so the path is made up of first words.
		<<11/16/2000; 7:41:36 AM by DW
			<<Added adrlastxstruct parameter. It points to the xstruct containing the last node in the walk. This is where we get the owner information, last modified, etc. It has to come from the walk.
		<<11/18/2000; 5:24:28 PM by DW
			<<Added adrrulestable parameter. When we return it contains a set of values, not unlike a paramtable, that controls the rendering of the directory.
		<<11/25/2000; 9:09:47 AM by DW
			<<Support cross-website inclusion. See call to
		<<11/26/2000; 7:27:13 PM by DW
			<<Run off the directories table.
		<<11/29/2000; 5:31:38 PM by DW
			<<Initially, a hyphen was a special character, we'd truncate everything after the hyphen when constructing a URL. This makes it difficult to include hypens, so I took the rule out today.
			<<Fixed breakage reported by Brent. There was a missing call to when we traverse a squiggled link. As a result, adrdirectoryinfo pointed into the wrong table, so it's not surprising that it couldn't find what it was looking for.
		<<12/14/2000; 8:50:13 AM by DW
			<<Add a parameter, the address of the url of the OPML file containing the source for the page. It must be initialized to point to the Manila dg message containing the outline, if the walk goes into an included opml file, it changes the url accordingly.
	<<local (adrmsg = mainresponder.discuss.getmessagetable (msgnum, adrroot:adrdiscussiongroup))
	if adrdirectories == nil { //store in system.temp.opmlDirectoryInfo
		adrdirectories = @system.temp.opmlDirectoryInfo};
	local (adrdirectoryinfo = (identifier, adrdirectories)); (adroutline, identifier, adrdirectoryinfo, ownername, owneremail);
	local (adrxstruct = @adrdirectoryinfo^.xmlstruct); //compiled OPML structure
	adrlastxstruct^ = adrxstruct;
	local (origpath = path);
	local (nomad = xml.getaddress (adrxstruct, "opml"));
	nomad = xml.getaddress (nomad, "body");
	new (tabletype, adrrulestable);
	on getrules (adr) {
		local (xmltext = "");
		on getxmltext (adrtable) {
			local (adr, name);
			for adr in adrtable {
				name = nameof (adr^);
				if name == "/atts" {
					xmltext = xmltext + adr^.text}
				else {
					if not (name beginswith "/") {
						getxmltext (adr)}}}};
		getxmltext (adr);
		xmltext = xml.entityDecode (xmltext, flAlphaEntities:true);
		<<wp.newtextobject (xmltext, @scratchpad.xmltext); edit (@scratchpad.xmltext)
		local (xstruct);
		xml.compile (xmltext, @xstruct);
		<<scratchpad.xstruct = xstruct; edit (@scratchpad.xstruct)
		bundle { //gather the rules from xstruct
			local (adr, name);
			for adr in @xstruct [1] {
				name = xml.converttodisplayname (nameof (adr^));
				if name == "rule" {
					local (startlevel, endlevel);
					if defined (adr^.["/atts"].level) {
						startlevel = adr^.["/atts"].level}
					else {
						startlevel = 1};
					if defined (adr^.["/atts"].["to"]) {
						endlevel = adr^.["/atts"].["to"];
						if endlevel == "infinity" {
							endlevel = 32767}}
					else {
						endlevel = 32767};
					local (adrval, adrrule);
					for adrval in adr {
						if not (nameof (adrval^) beginswith "/") {
							adrrule = @adrrulestable^.[xml.converttodisplayname (nameof (adrval^))];
							new (tabletype, adrrule);
							adrrule^.startlevel = number (startlevel);
							adrrule^.endlevel = number (endlevel);
							adrrule^.value = adrval^}}}}}};
	local (fladdtocrumblist = true);
	while path != "" {
		if path beginswith "/" {
			path = string.delete (path, 1, 1)};
		local (s = string.lower (string.nthfield (path, "/", 1)), adr, flfound = false);
		path = string.delete (path, 1, sizeof (s));
		if s beginswith "~" {
			if adrInSiteInclusionCallback == nil { //error
				scriptError ("Can't find the directory element because there is no item at \"" + path + "\". We ran into trouble at this element: \"" + s + "\".")}
			else {
				flfound = adrInSiteInclusionCallback^ (s, @nomad, @adrlastxstruct, adrcrumblist)}}
			<<bundle //original code
				<<local (othermsgnum)
				<<fladdtocrumblist = false
				<<bundle //set othermsgnum
					<<local (s = string.delete (s, 1, 1))
					<<if s endswith "~"
						<<s = string.delete (s, sizeof (s), 1)
						<<fladdtocrumblist = true
					<<othermsgnum = number (s)
				<<local (pta = html.getPageTableAddress ())
				<<local (adrdiscussiongroup = pta^.discussionGroup)
				<<local (adrmsg = mainresponder.discuss.getmessagetable (othermsgnum, adrroot:adrdiscussiongroup))
				<<local (adrdirectoryinfo = (nameOf (adrmsg^), adrdirectories))
				<< (adrmsg, adrdirectoryinfo)
				<<nomad = xml.getaddress (@adrdirectoryinfo^.xmlstruct, "opml")
				<<adrlastxstruct^ = @adrdirectoryinfo^.xmlstruct
				<<nomad = xml.getaddress (nomad, "body")
				<<if fladdtocrumblist
					<<adrcrumblist^ = adrcrumblist^ + {adrmsg^.subject}
				<<flfound = true
		else {
			if s endswith "~" {
				s = string.delete (s, sizeof (s), 1);
				fladdtocrumblist = true};
			for adr in nomad {
				if not (nameof (adr^) beginswith "/") { //it's an outline
					local (linetext = adr^.["/atts"].text);
					bundle { //decode any entities in the XML text
						linetext = xml.entityDecode (linetext, flAlphaEntities:true)};
					bundle { //catch rules
						if string.lower (linetext) beginswith "<rules>" {
							getrules (adr);
					local (text = string.lower ( (linetext)));
					<<msg (text + " == " + s + "?")
					if text == s {
						nomad = adr;
						bundle { //11/24/2000; 6:56:24 PM by DW
							<<If nomad points to a link, dive through the xmlstructs cache
								<<If this works I'll eat my hat. (I don't have a hat.)
								<<It works!
							try {
								if nomad^.["/atts"].type == "link" {
									local (url = nomad^.["/atts"].url);
									local (adrincache = (identifier, url, adrdirectories));
									if typeof (adrincache^) == tabletype {
										nomad = xml.getaddress (adrincache, "opml");
										nomad = xml.getaddress (nomad, "body");
										adrlastxstruct^ = adrincache;
										adrOpmlUrl^ = url}}}}; //12/14/2000; 8:51:05 AM by DW
						flfound = true;
						<<linetext = string.trimwhitespace (string.nthfield (linetext, '-', 1))
						linetext = string.trimwhitespace (linetext);
						if fladdtocrumblist {
							adrcrumblist^ = adrcrumblist^ + {linetext}};
		if not flfound {
			scriptError ("Can't find the directory element because there is no item at \"" + origpath + "\". We ran into trouble at this element: \"" + s + "\".")}};
	bundle { //on the way out, look for rules at the final level
		<<edit (nomad)
		local (adr);
		for adr in nomad {
			if not (nameof (adr^) beginswith "/") { //it's an outline
				if xml.entityDecode (adr^.["/atts"].text, flAlphaEntities:true) beginswith "<rules>" {
					getrules (adr)}}}};
	<<scratchpad.adr = nomad
	<<scratchpad.rules = adrrulestable^; edit (@scratchpad.rules)
	return (nomad)};
bundle { //test code
	local (crumblist, adrtoss, opmlUrl);
	local (adroutline =["0000001"].window);
	local (path = "/directoriesAtUserland/radioUserland");
	msg (walk (adroutline, "test", path, @crumblist, @adrtoss, @scratchpad.rules, @opmlUrl));
	edit (@scratchpad.rules)}

This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.