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

system.verbs.builtins.table.xmlToTable

on xmlToTable (xmltext, adrtable=nil) {
	<<Changes:
		<<1/31/03; 3:40:12 PM by JES
			<<Decode "alpha" entities in attribute values in the correct order.
		<<6/29/01; 3:13:54 PM by JES
			<<Fixed various problems with entity-decoding.
		<<6/28/01; 10:28:58 PM by JES
			<<Convert the XML representation of a table, into a Frontier table as specified here:
			<<http://smurfturf.manilasites.com/stories/storyReader$214
			<<s is the XML text
			<<adrtable is the address of the location to create the table.
				<<If nil, the table will be created at the address specified by the address attribute of the top-level <table> element.
	
	local (xstruct);
	xml.compile (xmltext, @xstruct);
	local (adrtablestruct = xml.getAddress (@xstruct, "table"));
	
	on getAttributeValue (adrelement, attname) {
		local (adratts = @adrelement^.["/atts"]);
		local (adratt = @adratts^.[attname]);
		local (value = xml.entityDecode (adratt^, false, true));
		value = string.replaceall (value, "<", "<");
		value = string.replaceall (value, ">", ">");
		value = string.replaceall (value, """, "\"");
		value = string.replaceAll (value, "'", "\'");
		value = string.replaceall (value, "&", "&");
		return (value)};
	
	if adrtable == nil { //get the address from the top-level <table> element
		try {
			adrtable = address (getAttributeValue (adrtablestruct, "address"))}
		else {
			scriptError ("Can't convert to a table because no destination address was specified.")}};
	
	on doListOrRecord (adrlist, adrdest, flrecord=false) {
		adrdest^ = {};
		local (adritem);
		for adritem in adrlist {
			if nameOf (adritem^) beginsWith "/" {
				continue};
			local (item); new (tableType, @item);
			if flrecord {
				local (name = getAttributeValue (adritem, "name"));
				main (adritem, @item, name);
				adrdest^ = adrdest^ + {name:item[1]}}
			else { //list
				main (adritem, @item, "item");
				adrdest^ = adrdest^ + item.item}};
		return (true)};
	on doOutline (adroutline, adrdest, flscript=false) {
		local (adropml);
		for adropml in adroutline {
			if xml.convertToDisplayName (nameOf (adropml^)) == "opml" {
				break}};
		local (xtext = xml.decompile (adropml));
		if flscript {
			local (s);
			op.xmlToOutline (xtext, @s);
			new (scriptType, adrdest);
			local (oldtarget = target.set (adrdest));
			op.insertOutline (@s, down);
			op.firstSummit ();
			op.deleteLine ();
			target.set (oldtarget)}
		else { //outline
			op.xmlToOutline (xtext, adrdest)};
		return (true)};
	on doMenubar (adrmenu, adrdest) {
		new (menubarType, adrdest);
		on addHeading (s, flfirstheading) {
			if flfirstheading {
				op.setLineText (s)}
			else {
				op.insert (s, down)};
			return (true)};
		on doLevel (adr) {
			local (adritem, flfirstheading = true);
			for adritem in adr {
				if nameOf (adritem^) beginsWith "/" {
					continue};
				local (itemtype = xml.convertToDisplayName (nameOf (adritem^)));
				case itemtype {
					"script" {
						local (name = getAttributeValue (adritem, "name"));
						addHeading (name, flfirstheading);
						local (commandKey);
						if defined (adritem^.["/atts"].commandKey) {
							commandKey = char (number (adritem^.["/atts"].commandKey))};
						if commandKey != nil {
							menu.setCommandKey (commandKey)};
						local (s);
						doOutline (adritem, @s, true);
						menu.setScript (@s)};
					"menubar" {
						local (name = getAttributeValue (adritem, "name"));
						addHeading (name, flfirstheading);
						op.insert ("", right);
						doLevel (adritem);
						op.go (left, 1)};
					"separator" {
						addHeading ("-", flfirstheading)}};
				flfirstheading = false}};
		local (oldtarget = target.set (adrdest));
		doLevel (adrmenu);
		target.set (oldtarget);
		return (true)};
	on doTable (adrtable, adrdest) {
		local (adritem);
		new (tableType, adrdest);
		for adritem in adrtable {
			if nameOf (adritem^) == "/atts" {
				continue};
			if nameOf (adritem^) == "/pcdata" {
				continue};
			local (name = getAttributeValue (adritem, "name"));
			main (adritem, adrdest, name)};
		return (true)};
	on main (adritem, adrdest, name) {
		local (typestring = xml.convertToDisplayName (nameOf (adritem^)));
		local (adritemdest = @adrdest^.[name]);
		case typestring {
			"table" {
				doTable (adritem, adritemdest)};
			"outline" {
				doOutline (adritem, adritemdest)};
			"script" {
				doOutline (adritem, adritemdest, true)};
			"wptext" {
				local (ix = 1; adrbody);
				loop { //find <body>
					if string.nthField (nameOf (adritem^[ix]), '\t', 2) == "body" {
						adrbody = @adritem^[ix];
						break};
					ix++};
				local (value);
				if typeOf (adrbody^) == tableType {
					value = xml.entityDecode (adrbody^.["/pcdata"], true)}
				else {
					value = xml.entityDecode (adrbody^, true)};
				wp.newTextObject (value, adritemdest)};
			"list" {
				doListOrRecord (adritem, adritemdest)};
			"record" {
				doListOrRecord (adritem, adritemdest, true)};
			"binary" {
				local (value = base64.decode (adritem^.["/pcdata"]));
				adritemdest^ = binary (value);
				setBinaryType (adritemdest, getAttributeValue (adritem, "type"))};
			"menubar" {
				doMenubar (adritem, adritemdest)}}
		else { //scalar
			local (value = getAttributeValue (adritem, "value"));
			adritemdest^ = [typestring] (value)};
		return (true)};
	
	doTable (adrtablestruct, adrtable);
	
	return (true)}
<<bundle //testing
	<<table.xmlToTable ("<table name=\"myTable\" address=\"workspace.myTable\"><string name=\"myString\" value=\"This is a string.\"/></table>")
	<<table.xmlToTable (string (workspace.foo), @workspace.deserializedTable)



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.