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

system.verbs.builtins.radio.backup.restoreOneMonth

on restoreOneMonth (xmltext, adrpoststable) {
	<<Changes
		<<12/1/02; 1:04:19 AM by JES
			<<Only encode numeric entities > 127, not "alpha" entities or "low-ascii" entities. Added some special handling for " and ' entities. Convert to Mac text accordingly.
		<<11/30/02; 11:58:14 PM by JES
			<<Save item description as a wptext object instead of as a string, in keeping with the original storage format.
		<<11/15/02; 1:05:47 PM by DW
			<<Created.
	bundle { //deal with " and ' entities
		<<Notes
			<<xml.compile decodes entities for <, >, and &, but it doesn't decode entities for ' or ".
			<<Take for example a post which contains the literal text -- the HTML entity, '. In an RSS file, this is represented as &apos;.
			<<When this XML is compiled, we get back to ', but there's a problem: When the literal text ' appears in an RSS file, it's encoded as ' -- the XML entity.
			<<Since xml.compile does not decode ' to ', what we end up with is a situation where we can't tell the difference between ' and &apos -- or in the XML, ' and &apos;.
			<<So -- we do the following decoding before calling xml.compile:
				<<" -> "
				<<&apos -> '
				<<&quot; -> "
				<<&apos; -> '
			<<This makes the entity encoding/decoding fully reversible, at least for content which does not contain any entity-encoded attribute values which contain the ' or " character -- which is the case for these RSS files.
		xmltext = string.replaceAll (xmltext, """, "\"");
		xmltext = string.replaceAll (xmltext, "'", "\'");
		xmltext = string.replaceAll (xmltext, "&quot;", """);
		xmltext = string.replaceAll (xmltext, "&apos;", "'")};
	local (xstruct);
	xml.compile (xmltext, @xstruct);
	<<scratchpad.xstruct = xstruct
	local (adrrss = xml.getAddress (@xstruct, "rss"));
	local (adrchannel = xml.getAddress (adrrss, "channel"));
	local (version = xml.getAttribute (adrrss, "version")^);
	local (flVersion20 = not date.versionlessthan (version, "2.0"));
	
	on decode (s) {
		<<return (xml.rss.decodeString (s, false))
		<<s = xml.entityDecode (s, false, true)
		bundle { //decode numeric entities whose value is > 127
			<<Notes
				<<xml.entityDecode decodes all numeric entities, even those less than 128. Problem is that xml.entityEncode only encodes numeric entities greater than 127, so the two routines aren't symetrical. Code in this bundle does symetrical decoding of numeric entities.
			local (s2, ixentity, ixsemi, c, cstr);
			loop {
				ixentity = string.patternMatch ("&#", s);
				if ixentity == 0 {
					s2 = s2 + s;
					break};
				s2 = s2 + string.mid (s, 1, ixentity - 1);
				s = string.delete (s, 1, ixentity + 1);
				ixsemi = string.patternMatch (";", s);
				if ixsemi == 0 {
					s2 = s2 + ("&#" + s);;
					break};
				cstr = string.mid (s, 1, ixsemi - 1);
				s = string.delete (s, 1, ixsemi);
				try { //c may non-numeric -- don't decode in this case
					c = number (cstr);
					if c > 127 and c < 256 { //convert to character
						s2 = s2 + char (c);
						continue}};
				s2 = s2 + ("&#" + cstr + ";");};
			s = s2};
		if system.environment.isMac {
			return (latinToMac.convert (s))}
		else {
			return (s)}};
	
	local (adritem);
	for adritem in adrchannel {
		if nameof (adritem^) contains "item" {
			try {
				local (t, id);
				new (tabletype, @t);
				bundle { //get the id
					local (adrid = xml.getAddress (adritem, "id"));
					local (namespace = xml.getAttributeValue (adrid, "namespace"));
					if namespace == "radioWeblogPost:" {
						id = adrid^.["/pcdata"]}};
					<<if number (id) == 161
						<<msg (id)
				wp.newTextObject (decode (xml.getValue (adritem, "description")), @t.text);
				t.when = date (xml.getValue (adritem, "pubDate"));
				try {t.title = decode (xml.getValue (adritem, "title"))};
				try {t.link = decode (xml.getValue (adritem, "link"))};
				bundle { //source
					try {
						local (adrsource = xml.getAddress (adritem, "source"));
						t.sourceName = decode (adrsource^.["/pcdata"]);
						t.sourceUrl = decode (adrsource^.["/atts"].url);
						t.sourceTime = date (xml.getValue (adritem, "sourceTime"))}};
				bundle { //enclosure
					try {
						local (adrenclosure = xml.getAddress (adritem, "enclosure"));
						new (tabletype, @t.enclosure);
						t.enclosure.length = number (adrenclosure^.["/atts"].length);
						t.enclosure.type = adrenclosure^.["/atts"].type;
						t.enclosure.url = decode (adrenclosure^.["/atts"].url)}
					else {
						try {
							local (adrenclosure = xml.getAddress (adritem, "enclosureError"));
							new (tabletype, @t.enclosure);
							t.enclosure.url = decode (adrenclosure^.["/atts"].url);
							t.enclosure.error = decode (adrenclosure^.["/atts"].error)}}};
				bundle { //categories
					new (tabletype, @t.categories);
					try {
						local (catlist = xml.getAddressList (adritem, "category"), cat);
						for cat in catlist {
							t.categories.[decode (cat^)] = true}}};
				bundle { //flNotOnHomePage
					t.flNotOnHomePage = false;
					try {
						local (adrflag = xml.getAddress (adritem, "flNotOnHomePage"));
						local (namespace = xml.getAttributeValue (adrflag, "namespace"));
						if namespace == "radioWeblogPost:" {
							t.flNotOnHomePage = true}}};
				adrpoststable^.[string.padwithzeros (id, 8)] = t}}}}
<<bundle //test code
	<<new (tabletype, @scratchpad.posts)
	<<restoreOneMonth (file.readwholefile ("C:\\Program Files\\Radio UserLand\\www\\backups\\posts\\2002\\10.xml"), @scratchpad.posts)
	<<for adr in @scratchpad.posts
		<<adrcompare = @weblogdata.posts.[nameof (adr^)]
		<<if sizeof (adrcompare^) != sizeof (adr^)
			<<edit (adrcompare)
			<<break



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.