Setting up a custom doctype for XMetaL

MathFlow has been designed to minimize the amount of work required to set up a new doctype. If MathFlow is to be used, the custom doctype must include the MathML 3.0 module. MathFlow doesn't place any restriction on how you embed MathML, but by following certain guidelines you can make your life easier.

In XMetaL, a custom doctype is specified by a DTD or XML Schema and related files. In order to illustrate how to set up a custom doctype, MathFlow for XMetaL comes with a sample project which takes the Journalist doctype and creates a Journalist_math doctype supporting MathML. All of the files for this project are located in <path-to-xmetal>\Author\MathFlow\developer\author.

The following sections illustrate step-by-step instructions for setting up a custom doctype for use with MathFlow.

Add the MathML 3.0 module to your DTD

The sample DTD is located at this path:

<path-to-xmetal>\Author\MathFlow\developer\author\journalist_math.dtd.

For journalist_math, the relevant lines are the following:

<!-- ============================================================= -->
<!--                         MATHML                                -->
<!-- ============================================================= -->
<!-- ===== UNCOMMENT THE FOLLOWING TO USE NAMESPACE PREFIXES =====
<!ENTITY % MATHML.prefixed "INCLUDE"> <!ENTITY % MATHML.prefix "mml"> -->
<!ENTITY % mathml-dtd PUBLIC "-//W3C//DTD MathML 3.0//EN" "mathml3.dtd">  %mathml-dtd;

Also, you need to define where MathML can be inserted, as in this example:

<!ENTITY % PhraseLevel "Citation | Emphasis | Strong |TT |
                        Underscore | InlineGraphic | Link |
                        Subscript | Superscript | ULink |
                        %MATHML.prefix;:math">

Add the MathML 3.0 module to your XML schema

There are two steps necessary to customize your XML Schema:

  1. Import the MathML Schema, as in this example:
    <xs:import namespace="http://www.w3.org/1998/Math/MathML" schemaLocation="mathml3.xsd"/>
  2. Add the <m:math> element as a possible child of the appropriate element, shown in this example:
    <xs:group name="equation.content">
    <xs:sequence>
    <xs:element minOccurs="0" ref="alt"/>
    <xs:choice>
    <xs:element maxOccurs="unbounded" ref="graphic"/>
    <xs:element maxOccurs="unbounded" ref="mediaobject"/>
    <xs:element maxOccurs="unbounded" ref="mml:math"/>
    </xs:choice>
    </xs:sequence>
    </xs:group>
    <xs:complexType name="inlineequation.content">
    <xs:sequence>
    <xs:element minOccurs="0" ref="alt"/>
    <xs:choice>
    <xs:element maxOccurs="unbounded" ref="graphic"/>
    <xs:element maxOccurs="unbounded" ref="inlinemediaobject"/>
    <xs:element maxOccurs="unbounded" ref="mathphrase"/>
    <xs:element maxOccurs="unbounded" ref="mml:math"/>
    </xs:choice>
    </xs:sequence>
    </xs:complexType>

Add the Math element to your customization file

The sample customization file is located at this path:

<path-to-xmetal>\Author\MathFlow\developer\author\journalist_math.ctm

First, the namespace prefix ("mml") needs to be defined. Under <DTDExtensions>, add the following element:

<NSPrefixMap>
<NSPrefixPair prefix="mml" ns="http://www.w3.org/1998/Math/MathML"></NSPrefixPair>
</NSPrefixMap>

Next, the MathML element (mml:math) needs to be defined. Under <ElementPropertiesList>, add the following element:

<ElementProperties>
    <Name ns="http://www.w3.org/1998/Math/MathML">mml:math</Name>
<LongDescription>Root MathML element</LongDescription>
    <PrettyPrintOptions>
        <NewLineBeforeStartTag/>
        <IndentContent/>
        <NewLineAfterEndTag/>
        <NewLineAfterStartTag/>
        <NewLineBeforeEndTag/>
    </PrettyPrintOptions>
</ElementProperties>

Note the MathML element (object) will end up showing as mml:mml:math in the ctm file.

Finally, the images of the MathML equation should be treated as type Image Element. The following attributes are used to position the image on the page: Height, Width, Valign (baseline). In addition, the Source (altimg) attribute identifies the path to the preview image for the equation. Under <Images>, add the following element:

<Image>
    <Name ns="http://www.w3.org/1998/Math/MathML">mml:math</Name>
    <Source-Attribute>altimg</Source-Attribute>
    <Height-Attribute>altimg-height</Height-Attribute>
    <Width-Attribute>altimg-width</Width-Attribute>
    <Valign-Attribute>altimg-baseline</Valign-Attribute>
</Image>

XMetaL Author

If the MathML namespace prefix for this custom doctype is not "mml" (the default prefix for MathFlow), you will need to update the On_Document_First_Draw macro. Uncomment all of the lines (except the first line). Change the value of UPREFIX (on line 2) to your MathML namespace prefix. The rest of the lines, which set other global variables, do not need to be changed.

For example, if your MathML namespace prefix is "m", then your On_Document_First_Draw macro should look like this:

    // Set the MathML namespace prefix  UPREFIX = "m";
    MATHMLURI = " xmlns:"+UPREFIX+"=\"http://www.w3.org/1998/Math/MathML\"";
    if (UPREFIX!="") {
      PREFIX = UPREFIX+":";
    }
    MATH = PREFIX+"math";
    // Set the page width (in pixels) for this custom doctype for image generation
    PAGEWIDTH = -1;
    // -1 = default page width
    Application.Run("MF_On_Document_First_Draw");

If you use the labeled row in a table or matrix, then the appearance of the equation image generated will depend on the page width being used. In this case there is an additional global variable, PAGEWIDTH, which can be set. The default value of this variable is -1, which means use the default page width in the image generator (600 pixels). To specify a different page width for this custom doctype, set the PAGEWIDTH variable accordingly. For example, to change the page width to 800 pixels, you would change the On_Document_First_Draw macro as follows:

    // Set the page width (in pixels) for this custom doctype for image generation
    PAGEWIDTH = 800;

XMetaL ActiveX

If the MathML namespace prefix for this custom doctype is not "mml" (the default prefix for MathFlow), you will need to update the On_Macro_File_Load macro. Change the value of UPREFIX (on line 27) to your MathML namespace prefix. For example, if your MathML namespace prefix is "m", then line 27 in your On_Macro_File_Load macro should look like this :

    UPREFIX = "m";

Add an entry for the <math> element to the cascading stylesheet

The sample cascading stylesheet file is located at this path:

<path-to-xmetal>\Author\MathFlow\developer\author\journalist_math.css.

An entry for the MathML element is entered as follows:

    mml:math
    {
    }

Add an entry for the <math> element to the HTML stylesheet

The sample HTML stylesheet file is located at this path:

<path-to-xmetal>\Author\MathFlow\developer\author\journalist_math_HTML_Style.xsl.

An entry for the MathML element is entered as follows:

    <xsl:template match = "*[local-name() = 'math']" priority = "1000">
        <IMG SRC="{@altimg}" HEIGHT="{@altimg-height}" WIDTH="{@altimg-width}" ALT="" ALIGN="absmiddle" />
    </xsl:template>

The ALIGN can be changed to meet your requirements.

While MathFlow adheres pretty closely to MathML standards, there are several non-standard issues worth noting.

MathFlow has many characters accessible via private code points. In most cases, there is also a standard way to reference them, e.g. a standard character plus an attribute. These can be found in the MathFlow Aliases column in the MathFlow Named Characters and Named Characters (PUA) tables in the Characters section.

In many cases, there are several almost identical Unicode characters. Given this, MathFlow generally has a preferred character, which is the same one you would get from the toolbar and palettes. While we tried to pick the most common version of such characters, many customers might already have policies on what their preferred characters are, and if so, they wouldn't always match up. Consequently, a character mapping feature was introduced, whereby users set up a charmap file which specifies translations from our preferred characters to the customer's preferred characters. The translation is done on all MathML coming in or going out of MathFlow.

You can set up a special file to change the numerical codes MathFlow reads and generates for some chosen entities:

<path-to-xmetal>\Author\MathFlow\auxiliary\charmap.txt

For example, you may want to use #x2329 instead of MathFlow's #x27E8 for an angled bracket.

To do this, you would have to specify it in an Incoming translation table (giving your code, #x2329, first, and MathFlow's #x27E8 after it) and in an Outgoing table (reversing the order). The Incoming table is used whenever MathML is read into the MathFlow Editor, or sent to generate an image. The Outgoing one when receiving the markup from the MathFlow Editor, before inserting it back into your XMetaL document. Most of the time you will end up writing entries in pairs, one for each table, but having two separate tables gives you the most flexibility for replacing codes.

The format of the charmap.txt file contains the following:

  • Lines starting with # are considered comments and ignored.
  • A line starting with [Incoming signals the beginning of the Incoming table. Any line following it is considered part of this table, until there is a line starting with [Outgoing, which signals any line following it is part of the Outgoing table.
  • Lines in the Incoming table should consist of a pair of codes (in the format #xnnnn, where 'n' stands for any hexadecimal digit). As mentioned, the first one is your desired code, the second one is MathFlow's code.
  • Lines in the Outgoing table also consist of a pair of codes, in the same format, but now the order is reversed: the first code corresponds to MathFlow's, the second one to your own code.

For the example mentioned above, the charmap.txt file could be this:

## Character Code Mapping for MathFlow
[Incoming Table]
# our angled bracket MathFlow's
#x2329 #x27E8
[Outgoing Table]
# MathFlow's angled bracket Ours
#x27E8 #x2329
##end of file
Note: this is a simple mechanism, and there are several limitations to its use, especially when changing the glyphs of entities. You should realize this only translates between MathFlow and the rest of the world, but it does not change MathFlow's internal workings. So, for example, if you map the code for phi to the one for phiv, and then add a phi in MathFlow's Editor, you will still see the glyph of phi in this editor's window. However, once you insert the markup back into XMetaL, the image generated should have the expected glyph, the one corresponding to phiv.

Likewise, this does not affect the way XMetaL itself renders characters. So, if you are viewing the MathML markup content in XMetaL (as opposed to viewing the preview images created by MathFlow) you will still see the glyphs corresponding to XMetaL's codes, not the ones you put in charmap.txt.