Skip to content

foxy_xml_tree ​

FoXy tree queries: lookups over a linearized array of tags, shared by the DOM (xml_file) and the index (xml_index).

The tags are stored in document order (start tags order); each tag knows its ID (its index), its parent ID (0 for a root tag) and, once tree_build_children is called, its children IDs.

Namespaces (Namespaces in XML 1.0) are resolved on demand, nothing is stored: the namespace of a tag is declared by the nearest xmlns:prefix (or xmlns, for an unprefixed name) attribute of the tag or of its ancestors.

Source: src/lib/foxy_xml_tree.f90

Dependencies

Contents ​

Variables ​

NameTypeAttributesDescription
DIGITScharacter(len=*)parameterDecimal digits.
REGEX_MSG_LENintegerparameterLength of a regular expression compile message.
MAX_POSITION_DIGITSinteger(kind=I4P)parameterDigits of a [n] position at most (an I4P).
XML_NAMESPACEcharacter(len=*)parameterNamespace bound to the xml prefix.

Derived Types ​

name_pattern ​

A tag name to match: a literal name or, if is_expanded, a namespace and a local name.

Components ​

NameTypeAttributesDescription
namecharacter(len=:)allocatableLiteral name, or local name if is_expanded.
uricharacter(len=:)allocatableNamespace (empty for no namespace) if is_expanded.
is_expandedlogicalThe name is expanded (namespace and local name).
is_validlogicalThe name can match (its prefix is declared).
is_anylogicalAny name matches (*).

Subroutines ​

tree_attribute_text ​

Return the value of the attribute named name of the tag with ID id (as tree_attribute); iostat is XML_NOT_FOUND if the tag or the attribute does not exist.

Attributes: pure

fortran
subroutine tree_attribute_text(tag, nt, id, name, value, iostat, iomsg)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.
namecharacter(len=*)inAttribute name.
valuecharacter(len=:)outallocatableAttribute value, empty if it does not exist.
iostatinteger(kind=I4P)outIO status.
iomsgcharacter(len=:)outallocatableIO message.

Call graph

tree_build_children ​

Build the children IDs lists (in document order) of all tags from their parents IDs, in O(n).

@note Appending each child to its parent list while parsing costs O(children^2) for a parent with many children.

Attributes: pure

fortran
subroutine tree_build_children(tag, nt)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inoutallocatableTags.
ntinteger(kind=I4P)inNumber of tags.

Call graph

tree_select ​

Select the tags matching a path expression (an XPath subset), returning their IDs in document order.

Grammar: steps separated by / (the next step matches the direct children) or // (the descendants, at any depth); a leading / anchors the first step to the root tags, a leading // or none searches it at any depth (as tree_find_all does with a path). A step is a name test (a name, * for any name, {uri}local in Clark notation; prefixes resolved by namespaces if passed, see tree_find_all) followed by predicates, applied in order:

  • [@a]: the tag has the attribute a;
  • [@a="v"] (or 'v'): the value of a (decoded, as tree_attribute returns it) is v;
  • [@a~="re"]: the value of a matches the regular expression re (StringiFor regex, anywhere);
  • [n]: the n-th tag (from 1) among its siblings that passed the previous predicates (as XPath: //b[1] is the first b child of each parent).

Blanks are allowed around the predicate tokens only. A malformed expression (or regular expression) selects nothing: column is the column of the problem (0 if there is none) and message says what it is.

@note Not pure: the regular expressions of the predicates are compiled (StringiFor regex%compile).

fortran
subroutine tree_select(tag, nt, expression, namespaces, ids, column, message)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
expressioncharacter(len=*)inPath expression, e.g. //event[@type="x"]/origin.
namespacescharacter(len=*)inoptionalNamespaces declarations of the names prefixes.
idsinteger(kind=I4P)outallocatableSelected tags IDs, empty if there are none.
columninteger(kind=I4P)outColumn of the problem, 0 if there is none.
messagecharacter(len=:)outallocatableProblem message, empty if there is none.

Call graph

select_failed ​

Report a problem of a selector expression at column at, selecting nothing.

fortran
subroutine select_failed(expression, ids, column, message, at, what)

Arguments

NameTypeIntentAttributesDescription
expressioncharacter(len=*)inPath expression.
idsinteger(kind=I4P)inoutallocatableSelected tags IDs, emptied.
columninteger(kind=I4P)outColumn of the problem.
messagecharacter(len=:)outallocatableProblem message.
atinteger(kind=I4P)inColumn of the problem.
whatcharacter(len=*)inProblem.

Call graph

skip_blanks ​

Skip the blanks of expression from column c.

Attributes: pure

fortran
subroutine skip_blanks(expression, c)

Arguments

NameTypeIntentAttributesDescription
expressioncharacter(len=*)inPath expression.
cinteger(kind=I4P)inoutCurrent column.

Call graph

select_predicate ​

Parse the predicate of a selector expression at column c (a [), moving c after it, and filter the selected tags by it (see tree_select); a problem empties ids and sets column and message.

fortran
subroutine select_predicate(tag, nt, expression, c, ids, column, message)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
expressioncharacter(len=*)inPath expression.
cinteger(kind=I4P)inoutCurrent column.
idsinteger(kind=I4P)inoutallocatableSelected tags IDs.
columninteger(kind=I4P)inoutColumn of the problem, 0 if there is none.
messagecharacter(len=:)inoutallocatableProblem message.

Call graph

merge_sort ​

Sort IDs in increasing order (merge sort, O(n log n)).

Attributes: pure, recursive

fortran
subroutine merge_sort(ids)

Arguments

NameTypeIntentAttributesDescription
idsinteger(kind=I4P)inoutIDs.

Call graph

resolve_namespace ​

Resolve the namespace of the tag with ID id (see tree_namespace); is_declared is false for a prefix not declared or a tag that does not exist.

Attributes: pure

fortran
subroutine resolve_namespace(tag, nt, id, uri, is_declared)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.
uricharacter(len=:)outallocatableNamespace, empty for no namespace.
is_declaredlogicaloutThe namespace is declared.

Call graph

next_path_segment ​

Pop the next not empty /-separated segment from a tags path; a / between braces (a namespace in Clark notation) is not a separator.

Attributes: pure

fortran
subroutine next_path_segment(rest, segment)

Arguments

NameTypeIntentAttributesDescription
restcharacter(len=:)inoutallocatablePath segments still to pop.
segmentcharacter(len=:)outallocatablePopped segment, empty if there are no more.

Call graph

Functions ​

tree_attribute_name ​

Return the name of the attribute with index a (source order) of the tag with ID id, empty if it does not exist.

Attributes: pure

Returns: character(len=:)

fortran
function tree_attribute_name(tag, nt, id, a) result(name)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.
ainteger(kind=I4P)inAttribute index.

Call graph

tree_attributes_number ​

Return the number of attributes of the tag with ID id, 0 if it does not exist.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_attributes_number(tag, nt, id) result(number)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_attribute ​

Return the value of the attribute named name of the tag with ID id.

@note If the tag or the attribute does not exist, an empty string is returned.

Attributes: pure

Returns: character(len=:)

fortran
function tree_attribute(tag, nt, id, name) result(value)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.
namecharacter(len=*)inAttribute name.

Call graph

tree_children ​

Return the IDs of the direct children of the tag with ID id, in document order.

@note The ID 0 is the document root: its children are the root tags (a sweep of all the tags); a tag's children are its children list, built by tree_build_children (the cost is the number of children).

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_children(tag, nt, id) result(ids)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_find_all ​

Return the IDs of all tags (in document order) matching name or path.

Matching rules:

  • name: tags named name at any depth or, if parent is passed, only the direct children of parent;
  • path: /-separated tags names; the first one is matched as name, each following one must be a direct child of the previous one; all the tags matching a segment are explored, thus repeated parents are handled.

Names are matched literally (prefix included), except:

  • {uri}local (Clark notation): tags with local name local in the namespace uri ({}local: in no namespace), whatever their prefix;
  • if namespaces is passed, every name: its prefix is resolved by the declarations of namespaces, written as in XML (e.g. xmlns="uri1" xmlns:p="uri2"), not by the document ones; an unprefixed name without a default declaration is in no namespace, a prefix not declared matches nothing.

@note If both name and path are passed, path is used; if none is passed, no tag is returned.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_find_all(tag, nt, name, path, parent, namespaces) result(ids)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
namecharacter(len=*)inoptionalTag name.
pathcharacter(len=*)inoptionalTags path, e.g. origin/latitude/value.
parentinteger(kind=I4P)inoptionalParent tag ID, 0 for the document root.
namespacescharacter(len=*)inoptionalNamespaces declarations of the names prefixes.

Call graph

tree_find ​

Return the ID of the first tag (in document order) matching name or path (see tree_find_all), 0 if none; a name is searched up to its first match only.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_find(tag, nt, name, path, parent, namespaces) result(id)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
namecharacter(len=*)inoptionalTag name.
pathcharacter(len=*)inoptionalTags path, e.g. origin/latitude/value.
parentinteger(kind=I4P)inoptionalParent tag ID, 0 for the document root.
namespacescharacter(len=*)inoptionalNamespaces declarations of the names prefixes.

Call graph

tree_level ​

Return the level of the tag with ID id (1 for a root tag), 0 if it does not exist.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_level(tag, nt, id) result(level)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_local_name ​

Return the local name (the name without prefix) of the tag with ID id, an empty string if it does not exist.

Attributes: pure

Returns: character(len=:)

fortran
function tree_local_name(tag, nt, id) result(local_name)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_matching ​

Return the IDs of ids (in their order) whose name (on=name) or the value of attribute (on=attribute) matches the compiled regular expression re (anywhere, or the whole text with whole); a tag without the attribute never matches, a regex not compiled matches nothing.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_matching(tag, nt, ids, re, on, attribute, whole) result(matched)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idsinteger(kind=I4P)inTags IDs to filter.
retype(regex)inCompiled regular expression.
oncharacter(len=*)inWhat is matched: name or attribute.
attributecharacter(len=*)inAttribute name (with on=attribute).
wholelogicalinMatch the whole text, not a part of it.

Call graph

regex_matches ​

Return true if the compiled regular expression re matches a part of subject (the whole of it with whole).

Attributes: pure

Returns: logical

fortran
function regex_matches(re, subject, whole) result(is_match)

Arguments

NameTypeIntentAttributesDescription
retype(regex)inCompiled regular expression.
subjectcharacter(len=*)inSubject.
wholelogicalinMatch the whole subject.

Call graph

tree_name ​

Return the name of the tag with ID id, an empty string if it does not exist.

Attributes: pure

Returns: character(len=:)

fortran
function tree_name(tag, nt, id) result(name)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_namespace ​

Return the namespace of the tag with ID id: the value of the nearest declaration of its prefix (xmlns:prefix, or xmlns for an unprefixed name) on the tag or on its ancestors; the xml prefix is bound to its namespace.

@note An empty string is returned for a tag in no namespace (unprefixed, without a default namespace declaration or with xmlns=""), for a prefix not declared and if the tag does not exist. A prefix cannot be declared empty (XML 1.0), thus a prefixed tag without namespace has its prefix not declared.

Attributes: pure

Returns: character(len=:)

fortran
function tree_namespace(tag, nt, id) result(uri)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_parent ​

Return the parent ID of the tag with ID id (0 for a root tag or if the tag does not exist).

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tree_parent(tag, nt, id) result(parent)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tree_prefix ​

Return the prefix of the name of the tag with ID id, an empty string if it has none or it does not exist.

Attributes: pure

Returns: character(len=:)

fortran
function tree_prefix(tag, nt, id) result(prefix)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.

Call graph

tags_indexes ​

Return the tags indexes [1:nt].

Attributes: pure

Returns: integer(kind=I4P)

fortran
function tags_indexes(nt) result(indexes)

Arguments

NameTypeIntentAttributesDescription
ntinteger(kind=I4P)inNumber of tags.

Call graph

attribute_filtered ​

Return the IDs of ids (in their order) having the attribute attribute (valued value, if is_valued).

Attributes: pure

Returns: integer(kind=I4P)

fortran
function attribute_filtered(tag, nt, ids, attribute, is_valued, value) result(filtered)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idsinteger(kind=I4P)inTags IDs to filter.
attributecharacter(len=*)inAttribute name.
is_valuedlogicalinThe attribute value is checked.
valuecharacter(len=:)inallocatableAttribute value (with is_valued).

Call graph

descendants_named ​

Return the IDs (in document order) of the tags matching pattern that are descendants of any of contexts.

@note A child ID is greater than its parent one, but a subtree is not a range of IDs (a built document numbers tags in insertion order): one forward sweep flags the tags in a subtree of the contexts, a descendant has a flagged parent.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function descendants_named(tag, nt, contexts, pattern) result(ids)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
contextsinteger(kind=I4P)inContext IDs (distinct), 0 for the document.
patterntype(name_pattern)inTag name to match.

Call graph

siblings_at ​

Return the IDs of ids (in document order) that are the position-th among the ones of ids with the same parent.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function siblings_at(tag, nt, ids, position) result(selected)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idsinteger(kind=I4P)inTags IDs (in document order).
positioninteger(kind=I4P)inPosition among the siblings, from 1.

Call graph

is_name_test ​

Return true if test is a valid name test of a selector step: *, a name, or {uri}local.

Attributes: pure

Returns: logical

fortran
function is_name_test(test) result(is_valid)

Arguments

NameTypeIntentAttributesDescription
testcharacter(len=*)inName test (not empty).

Call graph

find_tags ​

Return the IDs of the tags (in document order) matching name or path (see tree_find_all), only the first one if is_first.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function find_tags(tag, nt, name, path, parent, namespaces, is_first) result(ids)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
namecharacter(len=*)inoptionalTag name.
pathcharacter(len=*)inoptionalTags path, e.g. origin/latitude/value.
parentinteger(kind=I4P)inoptionalParent tag ID, 0 for the document root.
namespacescharacter(len=*)inoptionalNamespaces declarations of the names prefixes.
is_firstlogicalinOnly the first match is needed.

Call graph

children_named ​

Return the IDs (in document order) of the tags matching pattern that are direct children of any of parents (only the first one if is_first, for a single parent).

@note The children lists of the parents are walked (the roots, for parent 0, by a sweep): the cost is the number of children, not of tags. Children of different parents are sorted if needed (nested parents interleave them).

Attributes: pure

Returns: integer(kind=I4P)

fortran
function children_named(tag, nt, parents, pattern, is_first) result(ids)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
parentsinteger(kind=I4P)inParents IDs (in document order, distinct), 0 for the root.
patterntype(name_pattern)inTag name to match.
is_firstlogicalinOnly the first match is needed.

Call graph

declaration_name ​

Return the name of the attribute declaring the namespace of prefix (xmlns for no prefix).

Attributes: pure

Returns: character(len=:)

fortran
function declaration_name(prefix) result(name)

Arguments

NameTypeIntentAttributesDescription
prefixcharacter(len=*)inPrefix.

Call graph

is_matching ​

Return true if the tag with ID id matches pattern; an expanded name is checked on the local name first, the namespace (resolved through the ancestors) only if the local name matches.

Attributes: pure

Returns: logical

fortran
function is_matching(tag, nt, id, pattern) result(is_match)

Arguments

NameTypeIntentAttributesDescription
tagtype(xml_tag)inallocatableTags.
ntinteger(kind=I4P)inNumber of tags.
idinteger(kind=I4P)inTag ID.
patterntype(name_pattern)inTag name to match.

Call graph

name_local ​

Return the local name of a (qualified) name, prefix:local.

Attributes: pure

Returns: character(len=:)

fortran
function name_local(name) result(local_name)

Arguments

NameTypeIntentAttributesDescription
namecharacter(len=*)inName.

Call graph

name_pattern_of ​

Return the pattern matching name: expanded if name is in Clark notation ({uri}local) or if is_mapped (its prefix resolved by declarations), literal otherwise.

Attributes: pure

Returns: type(name_pattern)

fortran
function name_pattern_of(name, declarations, is_mapped) result(pattern)

Arguments

NameTypeIntentAttributesDescription
namecharacter(len=*)inName (not empty).
declarationstype(xml_tag)inNamespaces declarations, as attributes (used if is_mapped).
is_mappedlogicalinResolve the name prefix by declarations.

Call graph

name_prefix ​

Return the prefix of a (qualified) name, prefix:local, empty if it has none.

Attributes: pure

Returns: character(len=:)

fortran
function name_prefix(name) result(prefix)

Arguments

NameTypeIntentAttributesDescription
namecharacter(len=*)inName.

Call graph

separator_position ​

Return the position of the first / of path not between braces, 0 if there is none.

Attributes: pure

Returns: integer(kind=I4P)

fortran
function separator_position(path) result(s)

Arguments

NameTypeIntentAttributesDescription
pathcharacter(len=*)inTags path.

Call graph