The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

XML::XMetaL - Dispatch class for XML::XMetaL development framework

VERSION

This document refers to version 0.50 of XML::XMetaL, released 1st of August 2003.

SYNOPSIS

In XMetal .mcr files:

    ...
    <MACROS>
        <MACRO name="On_Macro_File_Load" key="" lang="PerlScript">
            <![CDATA[
                use XML::XMetaL;
                use XML::XMetaL::Custom::Bingo;
                my $handler = XML::XMetaL::Custom::Bingo->new(-application => $Application);
                $dispatcher = XML::XMetaL->new(-application => $Application);
                $dispatcher->add_handler(
                                            -system_identifier  => "bingo.dtd",
                                            -handler            => $handler
                );
                $dispatcher->On_Macro_File_Load();
            ]]>
        </MACRO>
        <MACRO name="On_Document_Save" key="" lang="PerlScript">
            <![CDATA[
                $dispatcher->On_Document_Save();
            ]]>
        </MACRO>
        ...
    </MACROS>

In XMetaL .ctm files:

    ...
    <OnInsertElementList>
        <OnInsertElement>
            <Name>section</Name>
            <Lang>PerlScript</Lang>
            <InsertElemScript>
                <![CDATA[$dispatcher->ctm_section()]]>
            </InsertElemScript>
        </OnInsertElement>
        ...
    </OnInsertElementList>
    ...

ABSTRACT

XML::XMetaL is a framework for object oriented XMetaL development using Perl. The framework makes it easy to write Perl classes that customize XMetaL. The advantages of using the framework are:

  • Object oriented development.

    Object oriented XMetaL application development, with nearly all code moved from XMetaL .mcr and .ctm files to Perl modules.

    In addition to the advantages of object oriented development, this makes it possible to use any editor for XMetaL development, not just Visual Studio (XMetaL 4+), or the built in editor (XMetaL 1.0 - 3.1).

  • Better control over shared functions and code reuse.

    There is no longer any need to use global customization files, such as xmetal.mcr to share functionality over several customization packages. Instead, common functionality is factored out into Perl modules and reused only by those customizations that need them.

    This reduces the risk of conflicts between different customizations installed on the same XMetaL client.

  • Automated unit and function testing.

    Using the framework it is possible to write automated unit and function tests for XMetaL applications using Test::More and other test frameworks.

  • Utility functions.

    Useful utility functions, including a word counter, id generator, common XMetaL constants, node iterator, and more.

DESCRIPTION

The XML::XMetaL class is a dispatcher for XMetaL customization handlers. XML:XMetaL objects are singletons. There can be only one XML::XMetaL object instantiated at any one time.

If an XML::XMetaL object already exists, the constructor (new) will just return the already existing object.

Customization handlers are registered and associated with a system identifier with the add_handler method.

When a method is called on a dispatcher (XML::XMetaL object), the dispatcher figures out which handler that should handle the call, and forwards the method call to the handler.

For example, calling On_Document_Save on the dispatcher, will make the dispatcher call the On_Document_Save method for the handler associated with the system identifier of the currently active document.

When the dispatcher calls a handler, the call is wrapped in an eval block. If an exception is thrown by the handler, it will be caught by the dispatcher and the error message will be shown in an XMetaL Alert box.

Constructor and initialization

    <MACRO name="On_Macro_File_Load" key="" lang="PerlScript">
        <![CDATA[
            use XML::XMetaL;
            use XML::XMetaL::Custom::Bingo;
            my $handler = XML::XMetaL::Custom::Bingo->new(-application => $xmetal);
            $dispatcher = XML::XMetaL->new(-application => $Application);
            $dispatcher->add_handler(
                                        -system_identifier  => "bingo.dtd",
                                        -handler            => $handler
            );
            $dispatcher->On_Macro_File_Load();
        ]]>
    </MACRO>

The constructor call must be placed in the On_Macro_File_Load macro in the .mcr file of an XMetaL customization package. This macro is executed when the XMetaL macro file is first loaded.

new
    C<new(-application => $Application)>

The constructor takes a single argument, the XMetaL application object. The $Application variable is instantiated automatically by XMetaL.

The XML::XMetaL objects are singletons, i.e. only one XML::XMetaL object can be instantiated. If the constructor is called a second time, it will just return the existing object.

add_handler
    $dispatcher->add_handler(
                                -system_identifier  => "bingo.dtd",
                                -handler            => "XML::XMetaL::Custom::Bingo"
    );

The add_handler method adds a handler for a particular XMetaL customization package. The handler must be a subclass of XML::XMetaL::Base. The handler is associated with a system identifier.

The system identifier is used to determine which handler to use with a particular document instance.

Class Methods

None.

Public Methods

None, but see the AUTOLOAD subsection below.

AUTOLOAD Method

Whenever a method is called on the dispatcher that does not exist, it is assumed that this is a method call that should be forwarded to a handler object.

AUTOLOAD generates a wrapper method that can forward the call to a handler and installs it in the symbol table. It then calls the newly created wrapper method.

The next time the method is called, it will already exist, and is executed directly, without going through the AUTOLOAD method.

The dispatch methods generated by AUTOLOAD will wrap calls to handlers in eval blocks. Errors trapped by the dispatch method will be displayed in an XMetaL Alert box. Handlers should preferably handle their own errors in a more graceful manner, but this provides a last ditch failsafe mechanism.

ENVIRONMENT

The Corel XMetaL XML editor must be installed.

BUGS

A lot, I am sure.

Please send bug reports to <henrik.martensson@bostream.nu>.

UTILITIES

gmcr.pl

Setting up macro files in XMetaL can be tedious. The gmcr.pl script automatically generates .mcr files containing the most common macro calls.

Output is to STDOUT by default, so it must be redirected to a file using the standard MSDOS redirection mechanism.

Example:

 gmcr.pl bingo.dtd XML::XMetaL::Custom::Bingo >bingo.mcr

Synopsis:

 gmcr.pl [-m] [-g] [-h] sysid module >outfile.mcr

 sysid       = The system identifier of the documents to be customized
               using the module
 module      - The Perl module used to customize XMetaL
 -f          - Add file events (Replaces XMetaL's default file open
               and save operations)
 -m          - Add mouse events (may slow XMetaL down)
 -g          - Add global macro events
 -h          - Print this help message
 outfile.mcr - An XMetaL macro file

The following event types can not be generated using gmcr.pl:

  • On_Drop_format

  • On_Drag_Over_format

TO DO

There are lots of things in the pipeline. The following list is just a few highlights. Whether they will ever be anything more than neat ideas depends on two things: how much time I have to work on them, and whether anyone is interested. (If you are, drop me an email. It will definitely improve your chance of seeing these features anytime soon.)

.ctm call generator

With XMetaL it is possible to trigger a script when tags are to be inserted. This is a very powerful mechanism, allowing such things as automated id generation and the insertion of complex, context dependent markup structures.

However, this requires customizing .ctm files. Up to XMetaL 3.1, a customization editor was included with XMetaL. In XMetaL 4.0, the customization editor is available only in the developer version. Furthermore, the customization editor is now a Visual Studio plug-in.

This is bad news for everyone that does not use Visual Studio. It is also bad news for Visual Studio users that want to do object oriented, and/or Perl development, because the XMetaL plug-ins for Visual Studio support neither.

Fortunately, .ctm files are just XML files, and can be edited in XMetaL, just like any other XML file. Adding calls to the dispather manually is tedious though. It is also time consuming. Even worse, it is error prone, because if the handler methods change, the .ctm file isn't updated automatically. It is very easy to add code for handling an element, or class of elements, and then forget to add calls to the code. It is even easier to remove code, and then forget to remove the calls.

Enter the .ctm call generator. It will analyse handlers, look for methods named ctm_elementname and add or remove method calls in the .ctm file as appropriate.

Whether the call generator will be just a Perl script, or a full blown XMetaL customization package in its own right, is still undecided. Whichever it will be, I hope to be able to include it in the next release.

Eventually, there will be some sort of support for Simple XLink, and possibly even Extended XLink support.

Public Identifier Support

I will add the capability to identify handlers based on public identifiers as an alternative to identification by system identifier.

This is useful because, unlike system identifiers, public identifiers are not tied to a physical location. (Well, this is fibbing a bit. System identifiers can be either URLs or URNs. URLs point to a location. URNs identify DTDs by name, much as public identifiers do. Unfortunately, URNs aren't very well supported by most XML applications.)

Dispatcher XML Schema Support

Currently, the dispatcher can't handle documents using XML Schema and XML Schema Instance (XSI). This is because the dispatcher looks in the doctype node to get the system identifier, but it does not know about XSI and xsi:schemaLocation attributes.

XML SchemaLocation Remapping

The xsi:schemaLocation attribute suffers from the same problems as the system identifier in a doctype: if it is a URL, pointing at a physical file, the document will not validate if the location of the schema is changed. If the URL is relative, even moving the document from one computer to another may make it impossible to validate.

URNs don't have this problem, but on the other hand, support for them isn't implemented in XMetaL.

The schemaLocation remapping functionality will make it possible to remap a URI that can't be resolved by XMetaL to a URL that can be resolved.

This might be done by implementing catalog file support in the remapping mechanism, or by some other mechanism.

XML::XMetaL::Utilities::TreeWalker

A treewalker for XMetaL. The treewalker will be able to process nodes while traversing them top-down or bottom-up.

Formatting Object Interface

The Formatting object interface in XMetaL 4.0 is accessible through JScript only. This is unfortunate, but it can be fixed.

I plan to implement access to the following functions through Perl:

previewHTML
previewPDF
saveAsHTML
saveAsPDF
XMLToHTMLSetup
XMLToPDFSetup
Class::Wrapper::XMetaL::*

This will be a set of decorator objects that wrap XMetaL objects and add new functionality to them.

For example Class::Wrapper::XMetaL::Documents could add the capability to handle Perl file handles to the Open method. It would be possible to add XLink and XInclude capabilities and other functionality that appear as if they are part of the standard XMetaL API.

Deployment

Currently there is no standardised way to deploy XML::XMetaL itself, or XML::XMetaL based module packages at the same time as deploying the XMetaL application (.dtd, .css, .mcr, .ctm, .tbr, and other files).

So far, I have just cobbled together a Perl script for handling the installation on a case by case basis.

A better solution is needed, particularly where there are a lot of clients to be updated.

PerlMSI might be the thing to use, but there are other alternatives. When I come up with a generic deployment solution, it will certainly make its way into an XML::XMetaL update.

XInclude Support

XInclude support is more of a "could come in handy" than a must have. At least for now.

SEE ALSO

See XML::XMetaL::Base, XML::XMetaL::Factory, XML::XMetaL::Registry, XML::XMetaL::Utilities, XML::XMetaL::Iterator, XML::XMetaL::Filter::Base.

AUTHOR

Henrik Martensson, <henrik.martensson@bostream.nu>

COPYRIGHT AND LICENSE

Copyright 2003 by Henrik Martensson

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.