mmxml
Topics covered in this chapter:
This module provides an XML parser and generator for the manipulation of XML documents from Mosel models. To use this module, the following line must be included in the header of the Mosel model file:
uses 'mmxml'
mmxml relies on the XML parser EXPAT by James Clark (http://www.libexpat.org) for loading documents.
Document representation in mmxml
Data model
The XML document is stored as a list of nodes. Different node types are used to represent the document structure:
In addition to these usual node types, the type DATA is used for XML constructs not supported by mmxml (for instance a DOCTYPE declaration is recorded as a DATA section). Although they are not directly recorded in the document tree, attributes are also stored as nodes of a dedicated type.
Each node is characterised by a name and a value. Nodes of type text, comment, CDATA and DATA have a constant name. The name of a processing instruction is the processing instruction's target and its value the remaining part of the statement (e.g. the name of <?proc inst> is proc and its value is inst). The value of comment and CDATA sections is the content of the section without its delimiters but the value of a DATA block includes the delimiters. Element nodes have also an ordered list of child nodes. The value of an element node corresponds to the value of the first child text node (if any).
The root node is a special element node with no name, no parent and no successor that includes the entire document as its children.
Example of an XML document with node types:
<?xml version="1.0" encoding="iso-8859-1" standalone="no" ?> | XML header |
<?xml-stylesheet type="text/css" href="examplestyle.css" ?> | Processing instruc. |
<!DOCTYPE exampleList SYSTEM "examples.dtd" [ | DATA |
![]() |
|
]> | |
<!-![]() ![]() |
Comment |
<exampleList> | Element node |
![]() ![]() ![]() |
Comment |
![]() |
Element node |
![]() |
Element node |
![]() |
Text node |
![]() |
|
![]() |
Element node |
![]() |
Element node |
![]() |
Element node |
![]() |
Text node |
![]() |
|
![]() |
Element node |
![]() |
Text node |
![]() |
|
![]() |
Element node |
![]() |
CDATA |
![]() |
|
![]() |
|
</exampleList> |
Paths in a document
Nodes can be retrieved using a path similar to a directory path used to locate a file. An XML path consists in a list of location steps separated by the slash character ("/"): each step selects a set of nodes from the input set resulting from the preceding step (context nodes). The initial set of the path is either the root node (absolute path) or some specified node (relative path).
A step is composed of an optional axis specifier followed by a node test and possibly completed by a predicate. The axis specifies the tree relationship between the nodes selected by the step and the context node. The node test is either an element name (to select elements of the given name) or a node type (to select nodes by their type). The predicate is a Boolean expression the truth value of which decides whether a selected node is kept in the result set of the step.
Examples:
- /examples/chapter
- all element nodes 'chapter' under elements 'examples'
- /examples/chapter/model/modRating[number()>=4]/..
- all 'model' nodes under 'examples/chapter' for which element 'modRating' has a value greater than or equal to 4
- //*[@attribute1 and @attribute2='value2']
- all element nodes of the document having 'attribute1' defined and 'attribute2' with value 'value2'
- /descendant::text()
- all text sections of the document
- .//mytag
- all element nodes named 'mytag' starting from the current node
Axis specifier
An axis specifier consists in an axis name followed the the symbol ::. The supported axes are:
- child
- children of the context node (this is the default if no axis is given)
- parent
- parent of the context node
- self
- the context node itself
- attribute
- the attributes of the context node
- following
- following node of the context node
- descendant-or-self
- the context node as well as all its descendants
- descendant
- all descendants of the context node
Node test
By default only element nodes are considered, the node test is used to select the nodes by their name. The special name "*" will keep all element nodes. Alternatively, the test can be related to the type of the nodes; in this case all nodes are considered and the test is one of the following expressions:
- text()
- to select text nodes
- comment()
- to select comment nodes
- cdata()
- to select CDATA nodes
- data()
- to select DATA nodes
- processing-instruction()
- to select processing instruction nodes
- node()
- to keep all nodes (independently of the type and name)
Abbreviated notation
Common combinations of axis-node tests have an abbreviated notation. The supported abbrevations are:
- .
- is equivalent to self::node()
- ..
- is equivalent to parent::node()
- //
- (used in place of /) is the same as descendant-or-self::node()
Predicate
A predicate is a Boolean expression enclosed in square brakets. The expression evaluator supports Boolean, text and numerical values (encoded as floating point numbers). Type conversions are implicit and implied by the operators: for instance the additive operator "+" operates on numbers, as a consequence its operands are systematically converted to numbers. Constant strings must be quoted using either single or double quotes.
The notation @attname designates the attribute which name is "attname": if used where a Boolean value is expected, it is true if the attribute is defined for the current node. Otherwise, this is the value of the attribute.
Supported arithmetic operators include +, -, *, div (division on floating point numbers, not integral division as in Mosel!), mod (modulo on floating point numbers). Boolean expressions can be composed using and and or; the usual comparators <, <=, >=, >, =, <> (or !=) can be applied to numbers. Note that equality testing (= and <>) is defined for all types. The following predefined functions can also be used in expressions:
- name()
- name of the node
- string()
- value of the node
- number()
- value of the node as a number
- boolean()
- value of the node as a Boolean
- position()
- position of the current node in the selected set (first node has position 1)
- not(boolexp)
- true if 'boolexp' is false, false otherwise
- true()
- value true
- false()
- value false
- string-length()/getsize()
- length of the node value
- string-length(strexp)/getsize(strexp)
- length of the text passed as parameter
- starts-with(strexp1,strexp2)
- true if text 'strexp1' starts with text 'strexp2'
- contains(strexp1,strexp2)
- true if text 'strexp1' contains text 'strexp2'
- round(numexp)
- rounded value of 'numexp'
- floor(numexp)
- floor value of 'numexp'
- ceiling(numexp)/ceil(numexpr)
- ceil value of 'numexp'
- abs(numexp)
- absolute value of 'numexp'
If the predicate [expr] is not a Boolean value, the whole expression is interpreted as [position()=expr].
JSON document as an XML tree
In addition to XML documents mmxml can also load and generate JSON documents represented as XML trees such that the information contained in the document can be handled using the routines published by this module. The procedure jsonload parses a JSON file that it maps to the internal XML representation using the following conventions: every JSON syntactic entity is converted to an XML element the value of which corresponds to the associated JSON value. The type of the value is identified via the attribute "jst" that can be "str" (string), "num" (numeric), "boo" (Boolean), "nul" (null object), "obj" (object) or "arr" (array). Names of object components can be mapped to either the name of the XML element or to an attribute (the behaviour of the parser is selected via an option of jsonload).
For instance, consider the following JSON document:
[{ "name": "bob", "age": 25, "student": true, "phone": [ { "type": "home", "number": "1234567900" }, { "type": "work", "number": "6789012345" } ] }]
It will be represented by the following XML document when object member names are turned into XML element names:
<?xml version="1.0" encoding="iso-8859-1"?> <jsv jst="arr"> <jsv jst="obj"> <name jst="str">bob</name> <age jst="num">25</age> <student jst="boo">true</student> <phone jst="arr"> <jsv jst="obj"> <type jst="str">home</type> <number jst="str">1234567900</number> </jsv> <jsv jst="obj"> <type jst="str">work</type> <number jst="str">6789012345</number> </jsv> </phone> </jsv> </jsv>
Note that with this representation the generated XML document is not necessarily valid XML (this mapping can for instance produce XML elements that have a number as name) and trying to export a JSON document using the save procedure may produce a file that cannot be processed by an XML parser. Using the second mode of operation avoids this problem: all elements are named "jsv" and object names are represented by attributes. The resulting XML document is larger than the one produced with the first mode:
<?xml version="1.0" encoding="iso-8859-1"?> <jsv jst="arr"> <jsv jst="obj"> <jsv jst="str" name="name">bob</jsv> <jsv jst="num" name="age">25</jsv> <jsv jst="boo" name="student">true</jsv> <jsv jst="arr" name="phone"> <jsv jst="obj"> <jsv jst="str" name="type">home</jsv> <jsv jst="str" name="number">1234567900</jsv> </jsv> <jsv jst="obj"> <jsv jst="str" name="type">work</jsv> <jsv jst="str" name="number">6789012345</jsv> </jsv> </jsv> </jsv> </jsv>
Assuming an XML tree has been built using the above conventions, the procedure jsonsave can be used to generate a JSON document. The XML document may combine the two representations described above and in most cases the jst attribute can be omitted. Therefore, jsonsave will produce the same JSON document as the example shown at the start of this section from the following XML file:
<?xml version="1.0" encoding="iso-8859-1"?> <jsv> <jsv> <name>bob</name> <jsv name="age">25</jsv> <student>true</student> <jsv name="phone"> <jsv> <type>home</type> <jsv name="number" jst="str">1234567900</jsv> </jsv> <jsv> <jsv name="type">work</jsv> <jsv name="number" jst="str">6789012345</jsv> </jsv> </jsv> </jsv> </jsv>
New functionality for the Mosel language
The type xmldoc
The type xmldoc represents an XML document stored in the form of a tree. Each node of the tree is identified by a node number (an integer) that is attached to the document (i.e. a node number cannot be shared by different documents and in two different documents the same number represents two different nodes). The root node of the document has number 0: the content of the document is stored as the children of this root node. In addition to structural properties (e.g. name, value, successor, parent) nodes have 2 formatting properties: vertical (setvspace) and horizontal (sethspace) spacing. These indications are used when the document is saved in text form for controling how the resulting text has to be organised (see save). The general formatting policy is defined by a set of document settings: indentation mode (setindentmode), indentation skip (setindentskip) and line length (setlinelen). Also used when exporting the documents are the XML version (setxmlversion), standalone status (setstandalone) and encoding (setencoding).
Procedures and functions
Add a node to a document tree.
|
|
Copy a node.
|
|
Delete an attribute of an element node.
|
|
Delete a node in a document tree.
|
|
Get the value of an attribute.
|
|
Get the character encoding of the document.
|
|
Get the first attribute of an element node.
|
|
Get the first child of an element node.
|
|
Get horizontal spacing of a node.
|
|
Get indent mode of the document.
|
|
Get the size of an indentation step.
|
|
Get the last child of an element node.
|
|
Get the length of a line.
|
|
Get the number of nodes currently allocated for a document.
|
|
Get the name of a node.
|
|
Get the successor of a node.
|
|
Get the first node returned by a path specification.
|
|
Get the list of nodes returned by a path specification.
|
|
Get the parent of a node.
|
|
Get the size of a document.
|
|
Get the standalone flag of the document.
|
|
Get the type of a node.
|
|
Get the value of a node.
|
|
Get vertical spacing of a node.
|
|
Get the XML version of the document.
|
|
Load a JSON document.
|
|
Parse a JSON document.
|
|
Save a JSON document.
|
|
Load an XML document.
|
|
Save an XML document.
|
|
Set the value of an attribute.
|
|
Set the character encoding of the document.
|
|
Set horizontal spacing of a node.
|
|
Set indent mode for the document.
|
|
Set the size of an indentation step.
|
|
Set the length of a line.
|
|
Set the number of allocated nodes for a document.
|
|
Set the name of a node.
|
|
Set the standalone flag of the document.
|
|
Set the value of a node.
|
|
Set vertical spacing of a node.
|
|
Set the XML version of the document.
|
|
Test existence of an attribute for a given element node.
|
|
Get an attribute during parsing of an element.
|
|
Decode a text string for XML.
|
|
Encode a text string for XML.
|
|
Parse an XML document.
|
© 2001-2025 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.