MJ - For a nice overview of WBXML read [L1 ].
A WBXML parser demonstrating the use of XOTcl mixins is shown below:
package require dict package require XOTcl namespace import ::xotcl::* Class Wbxml Wbxml instproc init { raw_wbxml } { my instvar raw tokens set raw [string toupper $raw_wbxml] set tokens [dict create] } Wbxml instproc parse {} { my instvar codepage cache raw strtbl xml set cache $raw set xml {} # reset codepages to 0 dict set codepage A 0 dict set codepage E 0 # puts "Parsing $raw" my unpack_version my unpack_publicid my unpack_charset my unpack_strtbl # assume no processing instructions in body so body is element my unpack_element } Wbxml instproc tagid_to_s {type tagid} { # by default we don't know any tags my instvar codepage tokens if {[dict exists $tokens $type [dict get $codepage $type] $tagid]} { return [dict get $tokens $type [dict get $codepage $type] $tagid] } else { # use default tag rendering return "${type}TOKEN_[dict get $codepage $type]_$tagid" } } Wbxml instproc unpack_element {} { my instvar cache codepage xml set tag [string range $cache 0 1] set cache [string range $cache 2 end] # check for codepage switch if {$tag eq "00"} { set newcodepage [scan [string range $cache 0 1] "%xx"] dict set codepage E $newcodepage set cache [string range $cache 2 end] return } scan $tag "%xx" tag_dec set attributes [expr ($tag_dec & 0x80)!=0] set contents [expr ($tag_dec & 0x40)!=0] set tagid [expr $tag_dec & 0x3F] set tagid [format "%X" $tagid] set tagtxt [my tagid_to_s E $tagid] set xml "${xml}<${tagtxt}" if $attributes { while {[string range $cache 0 1] ne "01"} { my unpack_attribute } set cache [string range $cache 2 end] } if $contents { set xml "${xml}>\n" while {[string range $cache 0 1] ne "01"} { my unpack_content } if {[string range $cache 0 1] ne "01" } { error "expected END token for tag $tagtxt, found [string range $cache 0 1] instead\n$cache" } else { set cache [string range $cache 2 end] set xml "${xml}</$tagtxt>\n" } } else { set xml "${xml}/>\n" } } Wbxml instproc unpack_charset {} { my instvar charset cache set raw_charset [string range $cache 0 1] set cache [string range $cache 2 end] set charsets [IANACharsets new -childof [self]] set charset [$charsets to_s $raw_charset] } Wbxml instproc unpack_content {} { my unpack_element } Wbxml instproc unpack_attribute {} { my instvar cache codepage xml set attrStart [string range $cache 0 1] set cache [string range $cache 2 end] # check for codepage switch if {$attrStart eq "00"} { set newcodepage [scan [string range $cache 0 1] "%xx"] dict set codepage A $newcodepage set cache [string range $cache 2 end] return } scan $attrStart "%xx" attrStart set attrStart [format "%X" $attrStart] set attribute [my tagid_to_s A $attrStart] # is string following? set next_token [format "%X" [scan [string range $cache 0 1] "%xx"]] if {$next_token == 3} { set cache [string range $cache 2 end] set attribute "$attribute\"[my unpack_string]\"" } elseif { [scan $next_token "%xx"] > 128 } { # well known attribute value set cache [string range $cache 2 end] set attribute "$attribute\"[my tagid_to_s A $next_token]\"" } set xml "$xml $attribute" } Wbxml instproc unpack_string {} { my instvar cache set result "" while {[string range $cache 0 1] ne "00"} { set result $result[format "%c" [scan [string range $cache 0 1] "%xx"]] set cache [string range $cache 2 end] } set cache [string range $cache 2 end] return $result } Wbxml instproc unpack_strtbl {} { # assume empty strtbl my instvar strtbl cache set cache [string range $cache 2 end] set strtbl {} } Wbxml instproc unpack_version {} { my instvar cache version set raw_version [string range $cache 0 1] set cache [string range $cache 2 end] set major [string index $raw_version 0] incr major set minor [string index $raw_version 1] dict set version major $major dict set version minor $minor } Wbxml instproc unpack_publicid {} { my instvar cache publicid set raw_publicid [string range $cache 0 1] set cache [string range $cache 2 end] # only support OMA Provisioning Documents for now TODO dict set publicid raw $raw_publicid set tmp [DocumentPublicIdentifier new -childof [self]] dict set publicid txt [$tmp pid_to_s $raw_publicid] # mixin specific functionality for the current my mixin [$tmp encoder_class $raw_publicid] #add tokens my add_tokens } Wbxml instproc display {} { my instvar version publicid strtbl cache charset xml puts "WBXML Version: [dict get $version major].[dict get $version minor]" puts "Document Public Id: [dict get $publicid txt] ([dict get $publicid raw])" # puts "Defined tokens [my tokens]" puts "Document charset: $charset" puts "String table: $strtbl" puts "Unparsed octets in last parse: $cache" puts "Parsed result:\n$xml" } # http://developer.sonyericsson.com/getDocument.do?docId=65055 Class WbxmlWapOta WbxmlWapOta instproc add_tokens {} { my instvar tokens dict set tokens E 0 5 characteristic-list dict set tokens E 0 6 characteristic dict set tokens E 0 7 parm dict set tokens A 0 6 {type="ADDRESS"} dict set tokens A 0 7 {type="URL"} dict set tokens A 0 8 {type="NAME"} dict set tokens A 0 11 {value=} dict set tokens A 0 12 {name="BEARER"} dict set tokens A 0 13 {name="PROXY"} dict set tokens A 0 14 {name="PORT"} dict set tokens A 0 15 {name="NAME"} dict set tokens A 0 17 {name="URL"} dict set tokens A 0 1C {name="GPRS_ACCESSPOINTNAME"} dict set tokens A 0 21 {name="CSD_DIALSTRING"} dict set tokens A 0 28 {name="CSD_CALLTYPE"} dict set tokens A 0 29 {name="CSD_CALLSPEED"} dict set tokens A 0 22 {name="PPP_AUTHTYPE"} dict set tokens A 0 23 {name="PPP_AUTHNAME"} dict set tokens A 0 24 {name="PPP_AUTHSECRET"} dict set tokens A 0 45 {value="GSM/CSD"} dict set tokens A 0 49 {value="GPRS"} dict set tokens A 0 61 {value="9201"} dict set tokens A 0 6B {value="9600"} dict set tokens A 0 70 {value="PAP"} dict set tokens A 0 73 {value="ISDN"} dict set tokens A 0 7C {type="MMSURL"} dict set tokens A 0 7F {value="BOOKMARK"} } WbxmlWapOta instproc display {} { my instvar raw puts "WAP OTA Provisioning Document" next } Class WbxmlOmaProv # microsoft specific: # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mobilesdk5/html/wce51congsmsmartphonepocketpcphoneeditionprovisioningwbxml.asp WbxmlOmaProv instproc add_tokens {} { my instvar tokens dict set tokens E 0 5 wap-provisioningdoc dict set tokens E 0 6 characteristic dict set tokens E 0 7 parm dict set tokens E 1 6 characteristic dict set tokens E 1 7 parm dict set tokens A 0 5 {name=} dict set tokens A 0 6 {value=} dict set tokens A 0 7 {name="NAME"} dict set tokens A 0 8 {name="NAP-ADDRESS"} dict set tokens A 0 9 {name="NAP-ADDRTYPE"} dict set tokens A 0 A {name="CALLTYPE"} dict set tokens A 0 C {name="AUTHTYPE"} dict set tokens A 0 D {name="AUTHNAME"} dict set tokens A 0 E {name="AUTHSECRET"} dict set tokens A 0 F {name="LINGER"} dict set tokens A 0 10 {name="BEARER"} dict set tokens A 0 11 {name="NAPID"} dict set tokens A 0 15 {name="PROXY-ID"} dict set tokens A 0 18 {name="PROVURL"} dict set tokens A 0 1C {name="STARTPAGE"} dict set tokens A 0 20 {name="PXADDR"} dict set tokens A 0 21 {name="PXADDRTYPE"} dict set tokens A 0 22 {name="TO-NAPID"} dict set tokens A 0 24 {name="SERVICE"} dict set tokens A 0 2F {name="PHYSICAL-PROXY-ID"} dict set tokens A 0 23 {name="PORTNBR"} dict set tokens A 0 46 {version="1.0"} dict set tokens A 0 50 {type=} dict set tokens A 0 51 {type="PXLOGICAL"} dict set tokens A 0 52 {type="PXPHYSICAL"} dict set tokens A 0 53 {type="PORT"} dict set tokens A 0 55 {type="NAPDEF"} dict set tokens A 0 56 {type="BOOTSTRAP"} dict set tokens A 0 5A {type="NAPAUTHINFO"} dict set tokens A 0 85 "IPV4" dict set tokens A 0 89 "APN" dict set tokens A 0 9A "PAP" dict set tokens A 0 AA "GSM-CSD" dict set tokens A 0 AB "GSM-GPRS" dict set tokens A 0 CB "CO-WSP" dict set tokens A 1 6 {value=} dict set tokens A 1 7 {name="NAME"} dict set tokens A 1 16 {type="CM_GPRSEntries"} ; #MS dict set tokens A 1 17 {type="DevSpecificCellular"} ; #MS dict set tokens A 1 1C {name="STARTPAGE"} dict set tokens A 1 22 {name="TO-NAPID"} dict set tokens A 1 28 {name="DestId"} ; #MS dict set tokens A 1 2A {name="UserName"} ; #MS dict set tokens A 1 2B {name="Password"} ; #MS dict set tokens A 1 3A {name="URI"} dict set tokens A 1 34 {type="ADDR"} dict set tokens A 1 36 {type="APPID"} dict set tokens A 1 39 {type="TO-PROXY"} dict set tokens A 1 55 {type="APPLICATION"} dict set tokens A 1 59 {type="RESOURCE"} dict set tokens A 1 61 {name="GPRSInfoAccessPointName"} ; #MS dict set tokens A 2 5 {type="BrowserFavorite"} ; #MS dict set tokens A 2 6 {name="URL"} ; #MS dict set tokens A 3 26 {name="REPLYADDR"} ; #MS } WbxmlOmaProv instproc display {} { puts "OMA Provisioning Document" next } # http://www.iana.org/assignments/character-sets Class IANACharsets IANACharsets instproc init {} { my instvar charsets dict set charsets 106 "UTF-8" } IANACharsets instproc to_s {id} { my instvar charsets scan $id "%xx" dec_id return [dict get $charsets $dec_id] } # http://www.wapforum.org/WINA Class DocumentPublicIdentifier DocumentPublicIdentifier instproc init {} { my instvar pids dict set pids 01 {{unknown (assuming WAP OTA v70)} WbxmlWapOta} dict set pids 0B { "-//WAPFORUM//DTD PROV 1.0//EN (Provisioning 1.0)" WbxmlOmaProv } } DocumentPublicIdentifier instproc pid_to_s { pid } { my instvar pids return [lindex [dict get $pids $pid] 0] } DocumentPublicIdentifier instproc encoder_class { pid } { my instvar pids return [lindex [dict get $pids $pid] 1] } package provide wbxml 0.1