Monday, November 08, 2010 at 12:06 AM.
system.verbs.builtins.table.tableToXml
on tableToXml (adrtable, flIncludeAddress=false) { <<Changes: <<1/31/03; 3:39:54 PM by JES <<Encode "alpha" entities in attribute values in the correct order. <<1/29/03; 2:36:29 PM by JES <<If present, strip out the "OPML generated by" comment at the top of the text returned by op.outlineToXml, when adding script or outline objects to the table XML. <<1/24/03; 7:45:55 PM by JES <<Small string concatenation optimization. <<1/14/03; 2:55:59 PM by JES <<Fixed a bug in generating XML for a filespec -- the filespec must be converted to a string before entity-encoding can take place. <<6/29/01; 12:19:25 PM by JES <<Added code to handle addresses, filespecs and directions, as specified by the spec. <<6/27/01 at 4:39:58 PM by JES <<Created. <<Convert a Frontier table to its XML representation, as specified here: <<http://smurfturf.manilasites.com/stories/storyReader$214 <<adrtable is the address of the table you want to serialize. <<If flIncludeAddress is true, then the top-level <table> tag will have an address attribute, specifying the address of the table in the object database. <<Returns the XML text representing the table. local (xmltext, indlev = 0); on add (s) { xmltext = xmltext + (string.filledString ('\t', indlev) + s + '\r');; return (true)}; on entityEncode (s) { s = string.replaceall (s, "&", "&"); s = string.replaceAll (s, "\'", "'"); s = string.replaceall (s, "<", "<"); s = string.replaceall (s, ">", ">"); s = string.replaceall (s, "\"", """); s = xml.entityEncode (s, false); local (i = 1, num); while i <= sizeof (s) { num = number (s [i]); if num < 32 { s = string.delete (s, i, 1); s = string.insert ("" + string.padWithZeros (num, 3) + ";", s, i); i = i + 5}; i++}; return (s)}; on getAtts (adr, name=nil) { local (t); new (tableType, @t); if name == nil and typeOf (name) == unknownType { t.name = entityEncode (nameOf (adr^))} else { if typeOf (name) != booleanType { t.name = entityEncode (name)}}; return (t)}; on addElement (elementname, cdata=nil, adratts=nil, flclose=true) { local (s = "<" + elementname); if adratts != nil { local (adratt); for adratt in adratts { s = s + " " + nameOf (adratt^) + "=\"" + adratt^ + "\""}}; if flclose { if cdata == nil { s = s + "/>"} else { s = s + ">" + entityEncode (cdata) + "</" + elementname + ">"}} else { s = s + ">"; if cdata != nil { s = s + entityEncode (cdata)}}; add (s); return (true)}; on doWpText (adr, name=nil) { local (t = getAtts (adr, name)); addElement ("wptext", adratts:@t, flclose:false); indlev++; addElement ("head", flclose:false); indlev++; addElement ("dateCreated", date.netStandardString (timeCreated (adr))); addElement ("dateModified", date.netStandardString (timeModified (adr))); bundle { //add <windowXxx> elements local (windowtop, windowleft, windowheight, windowwidth); local (oldtarget = target.set (adr)); //work around a kernel bug window.getSize (adr, @windowwidth, @windowheight); window.getPosition (adr, @windowleft, @windowtop); addElement ("windowTop", string (windowtop)); addElement ("windowLeft", string (windowleft)); addElement ("windowBottom", string (windowtop + windowheight)); addElement ("windowRight", string (windowleft + windowwidth)); target.set (oldtarget)}; add ("</head>"); indlev--; add ("<body>" + entityEncode (string (adr^)) + "</body>"); add ("</wptext>"); indlev--; return (true)}; on doOutline (adr, name=nil, flscript=false, commandKey="") { local (t = getAtts (adr, name)); if commandKey != "" { t.commandKey = number (commandKey)}; local (elementname = "outline"); if flscript { elementname = "script"}; addElement (elementname, adratts:@t, flclose:false); indlev++; local (opmltext = string.replaceAll (op.outlineToXml (adr), "\n", "")); opmltext = string.delete (opmltext, 1, sizeOf (string.nthField (opmltext, '\r', 1)) + 1); bundle { //remove "OPML generated by" comment, if present if opmltext beginsWith "<!-- OPML" { opmltext = string.delete (opmltext, 1, sizeOf (string.nthField (opmltext, '\r', 1)) + 1)}}; opmltext = string.filledString ('\t', indlev) + opmltext; opmltext = string.replaceAll (opmltext, '\r', "\r" + string.filledString ('\t', indlev)); opmltext = string.mid (opmltext, 1, sizeOf (opmltext) - 1); xmltext = xmltext + opmltext; indlev--; add ("</" + elementname + ">")}; on doMenubar (adr, name=nil) { local (t = getAtts (adr, name)); addElement ("menubar", adratts:@t, flclose:false); indlev++; local (localmenu = adr^); local (oldtarget = target.set (@localmenu)); op.firstSummit (); op.fullExpand (); on doOneLevel () { loop { local (l = op.getLineText ()); if l == "-" { addElement ("separator")} else { //a real menu command or sub-menu if op.countSubs (1) { //sub-menu local (t); new (tableType, @t); t.name = entityEncode (l); addElement ("menubar", adratts:@t, flclose:false); indlev++; op.go (right, 1); doOneLevel (); //dive add ("</menubar>"); indlev--; op.go (left, 1)} else { //menu command local (menuscript); menu.getScript (@menuscript); local (commandKey = menu.getCommandKey ()); if commandKey != "" { commandKey = commandKey[sizeOf (commandKey)]}; doOutline (@menuscript, l, true, commandKey)}}; if not op.go (down, 1) { return}}}; doOneLevel (); target.set (oldtarget); add ("</menubar>"); indlev--}; on doListOrRecord (adr, name=nil) { local (t = getAtts (adr, name)); local (elementname = "list"); local (flrecord = false); if typeOf (adr^) == recordType { elementname = "record"; flrecord = true}; addElement (elementname, adratts:@t, flclose:false); indlev++; local (ct = sizeOf (adr^)); for i = 1 to ct { local (item = adr^[i]); local (name = false); if flrecord { name = nameOf (adr^[i])}; main (@item, name)}; add ("</" + elementname + ">"); indlev--}; on doScalar (adr, name=nil) { local (atts = getAtts (adr, name)); local (elementname = string.typeToString (typeOf (adr^))); elementname = string.mid (elementname, 1, sizeOf (elementname) - 4); case typeOf (adr^) { filespecType; string4Type; stringType { atts.value = entityEncode (string (adr^))}; doubleType; longType { atts.value = adr^}; addressType { atts.value = entityEncode (string.popFileFromAddress (adr^))}; dateType { atts.value = date.netStandardString (adr^)}; charType { atts.value = number (adr^)}; booleanType { if adr^ { atts.value = "true"} else { atts.value = "false"}}; directionType { atts.value = string (adr^)}; unknownType { if adr^ == nil { elementname = "nil"} else { scriptError ("Can't serialize " + string.popFileFromAddress (adr) + " because unknownType objects are not supported in XML at this time.")}}} else { scriptError ("Can't serialize " + string.popFileFromAddress (adr) + " because " + string.typeToString (typeOf (adr^)) + " objects are not supported in XML at this time.")}; addElement (elementname, adratts:@atts); return (true)}; on doTable (adrtable, name=nil, flIncludeAddress=false) { local (adrstruct); //this points at the xstruct for the sub-item we're encoding local (t = getAtts (adrtable, name)); if flIncludeAddress { //add the address attribute to the <table> t.address = string.popFileFromAddress (adrtable)}; addElement ("table", adratts:@t, flclose:false); indlev++; local (adr); for adr in adrtable { main (adr)}; add ("</table>"); indlev--}; on main (adr, name=nil) { case typeOf (adr^) { binaryType { local (t = getAtts (adr, name)); t.type = getBinaryType (adr^); addElement ("binary", base64.encode (adr^, 0), @t)}; listType; recordType { doListOrRecord (adr, name)}; wpTextType { doWpText (adr, name)}; outlineType { doOutline (adr, name)}; scriptType { doOutline (adr, name, true)}; menubarType { doMenubar (adr, name)}; tableType { doTable (adr, name)}} else { //scalar doScalar (adr, name)}; return (true)}; doTable (adrtable, flIncludeAddress:flIncludeAddress); return (xmltext)} <<bundle //testing <<op.newOutlineObject (table.tableToXml (@workspace, true), @scratchpad.tableXml) <<edit (@scratchpad.tableXml)
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.