RAN provides delimiter-level support for specifying internal links between elements, without a schema. And for declaring attributes in bulk for a name prefix.
Anchors and Targets
RAN gives a lexical means of representing graph structures in a document without requiring a schema. A RAN document is therefore a sequence of trees overlaid with directed links between and inside them. One-to-one, one-to-many, many-to-one and many-to-many links are supported. An element may have multiple links.
A user should reasonably expect that anchors are indexed, that some kind of caching of links is performed, and that multi-factor matching against names in anchors is supported. Similarly, they should reasonably expect that attributes that are not anchors or targets do not have any special indexing.
An anchor is a special kind of attribute that identifies an element, for linking.
- The special delimiter == is used
- The attribute value may be
- a literal or name, which are treated equivalently
- a tuple of names and literals, in which case they all identify the element.
The anchor on a fragment start-tag is called the fragment key. It must appear as the first attribute. (More than one attribute may name anchors or targets.)
A link is a special kind of attribute that identifies one or more target elements
- The special delimiter =# is used for a normal forward link
- The special delimiter #= is used for a reverse link (between fragments only)
- The attribute value must be
- a literal, in which case it is the id of element(s) in the current fragment
- an anchor-path, which identifies the fragment key and perhaps other ancestor targets
- a URI,
- a relative path (to a file in the file system)
- a tuple of literals and or anchor-paths, in which case the link is to or from all the specified elements.
- The link can be named using the attribute name.
Because anchor-paths are used, the link may be a 1:many link, and may have wildcards.
By default, reverse linking (between fragments) is not active. To signal that the document has linking between fragments there must be a RAN PI at the end of the document that lists all fragments which have targets or anchors that participate in inter-fragment links.
<?RAN reverse-anchored=# [ otherfrag ] reverse-targetted=#[ somefrag] ?>
A RAN PI with these attributes that appears anywhere else in the document are ignore. This supports appending. With this information, a RAN processor can refrain from parsing fragments which do not have links. (The value *~ is a wildcard, meaning all fragments.)
Reverse links supports "out of band" markup: when appending fragments to a RAN stream, the links in a previous fragment can be augmented without changing that previous fragment. For example, we might have one fragment per human, with links from parent humans to their children. When a new child arrives, instead of adding a link to the parent's fragment, we can add a reverse link to the child's fragment and so not disturb or have to rewrite prior data. A new reverse link augments, not overwrites, other links.
A reverse link to an external resource may be specified, however there is no guarantee that this will make that resource aware that it has this implied links.
First we have a fragment x with various anchors specified.
<<x id=="f1">> <a> <b me==b23> <c ima="c34" /> </b></a> <</x>>
Next we have a fragment y which has a link with an anchor-path to identify the target.
<<y>> <look overthere=#f1+b23+c34 /> <</y>>
Anchor Paths are a new concept. They are like a simple XPath on the anchor names of the current RAN stream, but made with anchor values not element names.
- An anchor-path is a typed value (i.e. not in double quotes) that contains "+" or "~" not as the first character.
- A path of x+y+z means "the element with an anchor of 'z' , which is any descendant of the element whose anchor is 'y', which is an descendant of the fragment whose anchor is 'x'.
- + selects the lexically first path. If there are multiple matches, only the first is used.
- + establishes a 1:1 relation, or link. The name of the relation is the attribute name.
- A path of x~y~z means "all elements with an anchor of 'z' , which are descendant of alls element whose anchor is 'y', which are descendants of the fragment whose anchor is 'x'.
- ~ establishes a relation to all. If there are multiple matches, only the first is used.
- ~ establishes a 1:many relation. The name of the relation is the attribute name.
- * can be used as a wildcard
- * in the first position means "all fragments"
- * in the last position means "all elements with any anchor" (descendant of the preceding path)
If I have two element types Woman and Man, in a Fragment with fragment key "Royals" then the following are equivalent links (assuming the anchors are unique ids):
<Woman id=="Elizabeth_II" child =#["Charles" "Ann" "Andrew" "Edward" ]>...</Woman> <Man id=="Charles">...</Man> <Woman id=="Ann">...</Woman> <Man id=="Andrew">...</Man> <Man id=="Edward">...</Man>
<Woman id=="Elizabeth_II" >...</Woman> <Man id=="Charles" child #="Elizabeth_II" >...</Man> <Woman id=="Ann" child #="Elizabeth_II" >...</Woman> <Man id=="Andrew" child #="Elizabeth_II" >...</Man> <Man id=="Edward" child #="Elizabeth_II" >...</Man>
<Woman id=="Elizabeth_II" child =#["Charles" "Ann" "Andrew" "Edward" ]>...</Woman> <Man id=="Charles" child #="Elizabeth_II" >...</Man> <Woman id=="Ann" child #="Elizabeth_II" >...</Woman> <Man id=="Andrew" child #="Elizabeth_II" >...</Man> <Man id=="Edward" child #="Elizabeth_II" >...</Man>
<<Family who=="Royals" decade=195X >> <Woman id=="Elizabeth_II" child =#["Charles" "Ann"]>...</Woman> <Man id=="Charles" >...<Man> <Woman id=="Ann" >...<Woman> <</Family>> <<Family who=="MoreRoyals" decade=196X >> <Man id=="Andrew" child #=Royals+Elizabeth_II >...<Man> <Man id=="Edward" child #=Royals"Elizabeth_II >...<Man> <</Family>> <?RAN reverse-anchored=# ["Royals"] reverse-targetted=# ["MoreRoyals"] ?>
To explain this last example: we have a fragment for a Family (dated to the 1950s with a wildcard) where Elizabeth_II has child links to Charles and Ann. Then we append another fragment (dated to the 1960s with a wildcard) for Andrew and Edward: but rather than linking from Elizabeth to them, we have reverse links, which use anchor paths to first locate the fragment with anchor Royals and then the element in it with anchor Elizabeth_II.
It is a dynamic reportable error if a link dangles.
Link tags can appear in a document preamble. They allow definition of properties for a prefix, goes immediately after the open delimiters "<:". Any element tag name or fragment tag name that has a prefix is implicitly linked to the properties of the matched link tag.
There are two special prefixes that can be declared in link tags:
“"/"” for the whole document
“” for any element with no prefix in its name, or a name.
All attributes inside the link tag are properties of that document or element with a name with matching prefix.18
18Implementation Note: Represent XML namespaces using an attribute xmlns in a link tag. Represent links to schemas, code objects, stylesheets, using links. Put version and tracing metadata in a link tag. Metadata such as MIME metadata or Dublin Core may be exposed as a link tag. It can be used to transmit default values. (It might be good for RAN to specify most of these uses, adopting HTML-ish names where possible.)