We define flextags as a knowledge representation (KR) formalism by mapping to RDF and related languages.


Semi-formal syntax:

document ::= flextag? (break+ flextag)* break*
flextag ::= (param delim)+ hashtags? URL?
param ::= "[" param_body "]"
delim ::= anything else
param_body ::= '?' param_declaration
             | param_value
param_value ::= JSON_quoted_string | text_without_special_chars

A "break" is a paragraph break, which may depend on the syntax in which the content is embedded. In HTML, it would be a <p> tag. In twitter or plaintext, it would be a blank line.

Mapping to Simplified RDF

Each flextag maps to a graph of 0 or more paths out from a root node. The root node has the tag's URL if it has one, or is blank otherwise.

The mapping from flextags to graphs can be directly specified using a "flexmap", like this:

Given flexmap:

[? :p1] aaa [? :p2] bbb

the flextag:

hello aaa world bbb

maps to Turtle:

[] :p1 "hello";
   :p2 "world".

The flexmap can also provide fixed arcs:

[? :p1] aaa [? :p2] bbb # rdf:type :c1

and multiple names

[? :p1; rdfs:label] aaa [? :p2] bbb

Local names

Within one document, the special property _:localname is taken to be inverse-functional (at the syntactic level). All nodes with the same _:localname MUST be merged before yielding the RDF graph.

When outputting a graph with blank nodes in the object role, local names are generally required. (A few situations can be handled with paths.)

<xxx> :p1 _:y.
_:y :p2 2.
_:y :p3 3.

Could be serialized with tags like this:

This item has a p1 we'll call [yyy]. #flextag xxx
[yyy] has a p2 of [2] and and p3 or [3].

Pretty ugly, I know. Hopefully in the given domain, there's a natural label to use as the local name, like a person's name. But what if it's not unique in that document? Hmmm.


These can also be added in the flexmap:

[? :p1 ^^xs:boolean] aaa [? :p2 ^^xs:int] bbb


These can also be added in the flexmap:

[? :p1a/:p1b ^^xs:boolean] aaa [? :p2 ^^xs:int] bbb http://example.com


true aaa 5 bbb


<http://example.com> :p1a [ :p1b true ]; :p2 5.



Classic n-ary relation.


X of the media outlet y was a recipient of the Pulitzer prize in the category cc in the year yy

Ownership portion

X owns Y percent of company Z.

So we get

Sam Smith owns 0.00002 percent of company IBM.
Sam Smith owns 0.00002 percent of company Disney.
Alice Smith owns 0.00001 percent of company Disney.
Disney is ...
Sam Smith is ...

and that's fine, as long as there is only one Sam Smith.

ISSUE: we didn't use paragraph breaks. Who wants those?

If not, then maybe serialize later one as [Sam Smith #2].



Given a flexmap and an RDF graph, output as much of the graph as possible; provide the leftover (not output) portion on request.


Given a flexmap and a flextag document, parse the document to produce content for the graph.

Movable schema

The flexmap entries, with empty tags, can be used for defining a movable schema. Well, paths are a bit tricky, but mostly.

:p1 is_the_3rd_blank_of "some flexmap"


:p1 mov:propdef "The 3rd arg of this flexmap: ..."

:p1 mov:propdef "The 3rd arg, datatype xs:int, of this flexmap: ..."

:p1a mov:propdef "The 1st of 2 properties in a path which is the 3rd arg of this flexmap: ..."

That datatype thing isn't right; unsure how to do that kind of link.

non RDF

For non-RDF use, see dev.

There, flexmaps go to JSON-like objects.


Flexmap patterns should just be

?x ... ?y ... ?z.

No need for brackets. Let them be used for fill-ins.

Then the binding to RDF is with a construct if you want.

?url is automatic.


PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>

CONSTRUCT { ?x  vcard:N _:v .
            _:v vcard:givenName ?gname .
            _:v vcard:familyName ?fname }
    { ?x foaf:firstname ?gname } UNION  { ?x foaf:givenname   ?gname } .
    { ?x foaf:surname   ?fname } UNION  { ?x foaf:family_name ?fname } .
    FLEXTAG { ... ?x ... ?y ... ?z }.