Upgrade from 7.4 to 7.5

Required Changes

Recompile your schema

Fonto 7.5.0 fixes an issue with its schema compiler: schemata containing an element with an xs:anyAttribute were not correctly compiled. This occurred in the schema for MathML for instance. To prevent future issues, we require you to recompile your schema. This can be done using the FontoXML Development Tools with the command fdt editor schema compile.

Correct XPath reverse axes

Problem

We have upgraded our dependency on FontoXPath to 3.0.0. This version fixes an issue with reversed axes i.e. the ancestor, ancestor-or-self, preceding and preceding-sibling axes sometimes mistakenly returned their results in reverse document order. Editors may (accidentally) depend on this specific order. The issue occurred for (partial) XPath queries which contained a single step e.g. ancestor-or-self::* or preceding-sibling::div[@class="something"]. These queries used to result in a sequence containing the matching nodes in reverse document order instead of document order.

The same applies to expressions such as evaluateXPathToFirstNode('ancestor-or-self::*', ). This expression used to return the closest element ancestor of the context node, usually its parent element, whereas it will now return the first element ancestor in document order, usually the document element. Note that queries with multiple steps were unaffected by this issue. Queries such as (ancestor::div/parent::*)[1] correctly resulted in the parent of the first div in document order i.e. the topmost one. Predicates (the expression between the [] brackets) are always evaluated in the order of the local step i.e. preceding-sibling::*[1] always returns the closest preceding sibling.

Fix

Firstly, since only XPath queries with reverse axis steps were affected, a search for the reverse axis step names ancestor, ancestor-or-self, preceding and preceding-sibling will give you a full list of potentially affected queries. Secondly, since only single step queries were affected, queries with a / on either side of the step can be safely ignored. Thirdly, since only the order was reversed, all queries which disregard order can also be ignored. This includes queries like count(ancestor::*), self::*[ancestor::*] and not(preceding-sibling::*).

Note that queries evaluating to booleans were also unaffected i.e. the behavior of evaluateXPathToBoolean('ancestor-or-self::*') is unchanged. The same applies to parameters of type XPathTest, which are evaluated to booleans, e.g. the selectionAncestorNodeSpec parameter of setContextNodeIdToSelectionAncestor. However, the xPathQuery parameter of setContextNodeIdToFirstMatchingNodeFromContextNode, which is an XPathQuery, might be affected.

The fix is usually as simple as adding a [1] filter to the expression:

// Expressions like:
evaluateXPathToFirstNode('ancestor-or-self::div', node, readOnlyBlueprint)
// Should be rewritten to:
evaluateXPathToFirstNode('ancestor-or-self::div[1]', node, readOnlyBlueprint)