TBXs are just XML!

User beware! If you're looking it this likely you understand XML. Nonetheless keep backups. If you mess with the TBX file's source data it may become unreadable in Tinderbox.

Despite the file extension, the Tinderbox TBX file is a valid XML text file. Any proper XML editor/reader should be able to open/parse the document as 'raw' source data. Let's take a look at the overall structure…

The Tinderbox XML object structure

Above - illustrated in a Tinderbox file! - is the object structure of a TBX file. Points to note:

  • There are 2 sets of attribute objects. The first is for the built-in (always there) 'System' attributes. the second is for the optional user-added 'User' attributes.
  • The 'System' attributes are sub-nested into a series of groups that have no real significance outside Tinderbox.
  • The 'colors' object simply defines the 'built-in' Tinderbox colours, and any other added by the user. In the TBX color-type attribute values can be stored as hex (#ff0000) or as a 'defined colour name' string (bright red).
  • The 'menu' object. If any stamps (by default none) are present these are stored here.
  • The 'linkTypes' object lists the built-in/user-defined link types. The 'name' value is that used in the links table (see below) to indicate the type of an individual link).
  • The 'item' object. this may be considered the real data in the file. Items nest inside one another to reflect the outline view of the document. (More below).
  • The 'macros' object. User defined macro code, if any.
  • The 'preferences object. The document's current document-level preference defaults. this effectively presets in the app-level preference defaults as at the time the TBX was first saved.
  • The 'windows' object. Information about the size and positions of the document's open window(s).

The root <item> object

Notes:

  • The item has a 10-digit UID. Aliases retain their UID as long as they are not destroyed/rebuilt (e.g. aliases in agents).
  • Alaises. These include a special attribute : <attribute name="Alias" >[UID #]</attribute>. Only alaises will have this attribute.
  • Adornments: these replace the 'item' tag with an 'adornment' tag, but otherwise the same elements may be contained by the tag. Adornments never have child items.
  • Agents: these replace the 'item' tag with an 'agent' tag, but otherwise the same elements may be contained by the tag. Agents contain an internal attribute: <attribute name="Agent" >true</attribute>. Agents nest aliases of any items matching their query.
  • Attributes. Specific attributes are included but only/if they contain non-default values. If a value is re-set to the default it will be removed from the stored content. This avoids file bloat.
  • <text>. This is the note's 'plain' text as a UTF-8 XML encoded string. Only present if $Text has been added, and removed if $Text is subsequently deleted.
  • <styles>. These mark runs of individual font/bold/italic/underline/font colour within the above text. Only added if <text> is present, but always then added - i.e. even if $Text isn't further styled from defaults.
  • <rtf>. this is an XML-encoded representation of the above 'text' but in RTF allowing representation of effects like background highlighting, etc. Occasionally data pasted into Tinderbox notes may cause non-XML safe data here which manifests when the TBX is next opened. So, as long as a TBX opens in Tinderbox, this object should be regarded as safe to use/parse in an XML environment. Added if <text> is added.

The root <item> object's name is the name of the TBX file (without extension) and contains the entire user content outline consisting of 4 types of object:

  • <item>
  • Alias <item>
  • <adornment>
  • <agent>

These types of object are described below. The root <item> is functionally the same as an <item> object in terms of attributes, etc. although it has no text window so has no text windows so can't set $Text via the UI. However, it does act as the background to root-level major views so may need to be customised for things like the colour of the view background.

A generic item object

An item is illustrated above. It may, if not an alias, contain <item>, <adornment> and <agent> tags. The minimal set of attributes written for a non-alias 'item' are:

  • Created
  • Modified
  • Name
  • Xpos
  • Ypos

Other attributes are only added if storing non-default values.

An <agent> object

An <agent> object

An agent generally includes the same contents as is illustrated above for an item. It may contain only alias <item> or <adornment> tags. The minimal set of attributes written for an 'agent' are:

  • Agent (a hidden internal attribute). Value will be 'true'
  • Agent Query (even if empty)
  • Created
  • HTMLExportChildren, set to 'false'
  • IsPrototype (false, default)
  • Modified
  • Name
  • Xpos
  • Ypos

Other attributes are only added if storing non-default values. The HTMLExportChildren and IsPrototype settings are probably old workarounds to support issues in early versions.

An <adornment> object

An <adornment> object

An adornment generally includes the same contents as is illustrated above for an item. It may not contain other tags. The minimal set of attributes written for an 'adornment' are:

  • Created
  • Height
  • Modified
  • Name
  • Searchable
  • Width
  • Xpos
  • Ypos

An alias <item> object

An alias <item> object

An alias is included a special form of 'item'. It may not contain other tags. The minimal set of attributes written for an 'adornment' are:

  • Alias (a hidden internal attribute). Value will be the $ID of the aliases' original note.
  • Created
  • Modified
  • Name - the value is blank [sic]
  • Xpos
  • Ypos

Otherwise an alias will only store intrinsic attributes. Indeed, the $Name is intrinsic so it is important not to set it so it doesn't masked the original's $Name.

Alaises can have links differing from their original (though these are all consolidated in the links table.

Don't forget - backup

If you edit the XML and change it, you may make it unreadable for Tinderbox. So even if just extracting data from the file it's a good idea to work with a copy of the original to avoid unexpected outcomes.