Namespaces
This is a guide on how FontoXML APIs can be used to accommodate for the use of namespaces, both in XML and in XPath and XQuery.
Starting from the 7.0 version of FontoXML, the editor supports namespaces. If your schema uses namespaces and your application manipulates nodes directly, make sure to use the namespace related functions (with names ending in N
) present on DOM nodes and Blueprint, such as create
and get
. This ensures that new elements and attributes are assigned to the correct namespace. Alternatively, use the convenience APIs such as Stencils or Json
Do my documents use namespaces?
This guide only applies to editors loading documents which use namespaces. Most editors use them in one way or another, either by using namespaces themselves, like the TEI or the JATS standards. Or by including other schemas, like MathML.
If an editor loads documents containing prefixed elements, or if an xmlns
attribute is present, the editor should use namespaces. In general, it is preferred to use namespace related functions ending with NS (like createElementNS) over the normal functions (like createElement).
Introduction to namespaces
Namespaces are a way to use elements from different schemas into a single document. This is done by adding a URI to the name of an element. These URIs can be bound to a prefix for the sake of readability.
XML
<mml:math xmlns:mml="https://www.w3.org/1998/Math/MathML/">
// A piece of mathML here
</math>
Namespaces do not have to have a prefix. A namespace without a prefix is called the 'default namespace'. XHTML usually does not use a prefix:
XML
<html xmlns="https://www.w3.org/1999/xhtml/">
// A piece of XHTML
</math>
The namespace declaration does not have to exist at the top level element. It may exist at any (inclusive) ancestor of an element 'in' the namespace.
XML
<html xmlns="https://www.w3.org/1999/xhtml/">
<body xmlns:mml="https://www.w3.org/1998/Math/MathML/">
<p>
<mml:math>
// A piece of mathML here
</math>
</p>
</body>
</math>
Elements do not have to be in a namespace. For example, the DITA standard requires all DITA elements to be in the null namespace. The 'null namespace' is the namespace without a URI and without a prefix.
XML
<topic>
// A piece of dita content here
</topic>
Attributes work similarly. An attribute with a prefix exists 'in' the namespace associated with this prefix. However, attributes without prefixes always exist in the 'null namespace', not the default one.
XML
<p>
XLink defines a number of attributes <emph xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="...">in the xlink namespace</emph>.
</p>
<p>
Attributes lacking a prefix <emph color="blue"> are in the null namespace</emph>.
</p>
<p xmlns="http://example.com/ns">
Defining a default namespace <emph color="pink">does not affect this</emph>.
</p>
The full name of an element is called a qualified name
. The part before the colon is called the prefix
. The part after the colon is called a local name
.
Namespaces can only apply to elements and attributes. There is no such thing as a comment or processing instruction 'in a namespace'.
X Path and namespaces
The XPath and XQuery implementation used by FontoXML also supports namespaces. It is provided with the NamespaceQ{}
syntax can be used.
XQuery
descendant::Q{https://www.w3.org/1998/Math/MathML/}math/attribute::Q{http://www.w3.org/1999/xlink/}href
The XPath engine does not yet fully support namespace usage for types. Namespace prefixes that are used only for defining custom XPath functions using register
JavaScript
registerCustomXPathFunction({localName: 'do-something', namespaceURI: 'http://www.example.com/custom-function'}, [ ], 'xs:string?', function (dynamicContext) {
...
});
Namespace related AP Is
Registering namespaces
Before FontoXML can use a namespace, it must be registered. This can be done in a configuration.js
file, using the Namespace
Using an up to date version of FDT, namespace configuration is automatically generated when initializing a new Fonto Editor instance. However we might not be able to use a user friendly prefix, and use a numbered prefix, for example ns1.
If possible change these generated prefixes to something sensible, and make sure to update the selectors for the CVK family configuration of the elements in the sx-module
s accordingly.
configuration.js
JavaScript
// Register the XHTML namespace without a prefix. This a analogous to 'xmlns="https://www.w3.org/1999/xhtml/"'
namespaceManager.addNamespace(null, 'http://www.w3.org/1999/xhtml/');
// Register the MathML namespace, using the mml prefix. This is analogous to 'xmlns:mml="https://www.w3.org/1998/Math/MathML/"'
namespaceManager.addNamespace('mml', 'http://www.w3.org/1998/Math/MathML/');
// Also register a prefix for any application-specific XPath functions.
// Both the prefix and the namespace URI can be chosen by the application. This can be the same one as the namespace URI schema for which the editor is built, for example.
namespaceManager.addNamespace('app', 'http://www.fontoxml.com/app/your-app-name-here');
Creating elements
The namespace manager can also be used to create elements:
JavaScript
// Create an element in the XHTML namespace (which is bound to the empty prefix)
var xhtmlElement = namespaceManager.createElement(documentNode, 'html');
// Create a math element, in the mathML namespace (which is registered to bind to the mathml namespace URI)
var mathElement = namespaceManager.createElement(documentNode, 'mathml:math');
By using Json
JavaScript
var dom = jsonMLMapper.parseNode(documentNode, [
'html',
[
'body',
[
'p',
[ 'mathml:math' ]
]
]);
Note that it is unnecessary to mention the xmlns:whatever
'attributes'. The namespace manager will be used to resolve these prefixes, and the xmlns
attributes will be added as needed when the document is serialized.
It is also possible to use the namespace related methods on Document like create
, or the create
method on Namespace
Setting and getting attributes
The namespace manager can also be used to resolve a prefix to a uri. This uri can then be used to work with attributes:
JavaScript
var qname = namespaceManager.resolveQualifiedNameForAttribute(element, 'xlink:href');
blueprint.setAttributeNS(element, qname.namespaceURI, qname.qualifiedName, 'Some value');
blueprint.getAttributeNS(element, qname.namespaceURI, 'href');
// It is also possible to 'hard-code' the prefix like this:
blueprint.getAttribute(element, 'xlink:href');
// Many attributes do not use a prefix. For these attributes, the normal setAttribute methods suffice
blueprint.setAttribute(element, 'color', 'blue');
Higher level APIs like Json
Using the set
method with a prefixed name may yield unexpected results. This will correctly edit an attribute, but can not be used to create the attribute if it does not exist. To avoid this, always use the *NS methods when dealing with namespaced attributes.
Limitations
At this moment, FontoXML requires the relation between prefixes and namespaces to be one-to-one. One prefix may only bind to one URI and vice versa. Because of this, namespace overriding is not possible in the 7.0 version of FontoXML.