fxmacro

  1. What is fxmacro?
  2. Download
  3. Installing
  4. Usage
What is fxmacro?

fxmacro is a type-safe macro system for XML. XML is originally designed for the use in document processing. Every classical document processing system supports a mechanism which is called macro. In general, a macro is a named collection of actions. These actions are executed whenever the name of the macro appears in a document instance.

In C (GNU compiler collection) any name may be defined with any replacement text. For example,

#define forever for(;;) 
defines a new word, forever, for an infinite loop. It is also possible to define macros with arguments, so the replacement text can be different for different calls of the macro. (B.W.Kernighan, D.M.Ritchie. The C Programming Language)

Or, think of LaTeX where the macro

\def\sig#1{%
   \noindent
   \rule{.2\linewidth}{.3pt}\\
   ({\small #1})%
} 
expands to a line for a signature.

In fxmacro, any element-name may be defined with any replacement text. This replacement text can consist of normal text and markup. And it is also possible to define macros with arguments. See Usage for further information and examples. fxmacro is based on the functional XML parser fxp.

Download

Current version: Version 0.1 of fxmacro

Installation

Usage

This macro language for XML is very small and uses XML for both, defining and calling macros. Therefore it is easy to define some nice macros. Suppose that we are using an XML based mailtool to create and read our mail. The following document type definition (DTD) specifies how the elements inside a mail should relate to each other.

<!ELEMENT email     (header,body,signature) >
<!ELEMENT header    (from,to+,cc*,subject,reply-to?) >
<!ELEMENT from      (#PCDATA) >
<!ELEMENT to        (#PCDATA) >
<!ELEMENT cc        (#PCDATA) >
<!ELEMENT subject   (#PCDATA)*>
<!ELEMENT reply-to  (#PCDATA) >
<!ELEMENT body      (#PCDATA) >
<!ELEMENT signature (#PCDATA) > 
A mail consists of a header, a body and a signature. The header contains information about who authored the message, the intended recipients and the subject of the message. The body contains the information the sender is trying to communicate. And signature is a personal footer which is added to each outgoing message. Now let us define two very simple macros:
<def macro='bart'>bart@springfield-elementary.edu</def>
<def macro='f'><from><bart/></from></def> 
Every time these macros are used in a document instance they will produce the same output because they do not depend on any input. The new macro element 'f' does not have any content, it is an empty element. Each macro call <f/> will be replaced by
<from>bart@springfield-elementary.edu</from>.  
In a macro definition every already defined macro can be used. The macro definition of 'f' uses macro 'bart' to produce the content of 'from'. The next macro, 'family', expands to a forest consisting of three 'to' elements. Creating a new message, this macro can be used as a mail alias to send the message to every family member.
<def macro='family'>
   <to>homer.simpson@snpp.com</to>
   <to>marge@freemail.org</to>
   <to>lisa@freemail.org</to>
</def> 
If macros do not have arguments macro processing becomes text replacement. Now we want to look at macros with arguments. Normally, the 'from' and 'reply-to' fields are the same in every mail we send. Therefore it would be useful to define a macro that takes only the recipients and the subject as input while the other fields of the header are produced automatically. Such a macro looks like
<def macro='h'>
   <header>
      <f/>
      <par/>
      <subject><par p='2'/></subject>
      <reply-to><me/></reply-to>
      </header>
   </def> 
Macro 'h' takes two forests as arguments. These forests will be inserted at the corresponding places. The first argument contains the recipients and the second argument the subject of the message. The special element <par p='i'/> is a reference to the forest with number i. The input forests are numbered from left to right starting with 1. The element <par/> is an abbreviation for <par p="1"/>. A call of this macro can be
<h><family/><sep/>Radioactive Man</h> 
The macro element 'family' expands to several 'to' elements. The empty element <sep/> is a reserved element of the macro language. It is used to separate the different input forests. The second argument is the text "Radioactive Man". During expansion this text is placed between the start- and end-tag of the subject element. For our typechecking algorithm it is necessary to type the input forests of the macro. The type is given in the syntax of XML content models. On the basis of this type information the macro processor computes a type expression for the output forest. According to the DTD it is easy to see that after the 'from' element one or more 'to' elements follow, then optionally 'cc' elements followed by a subject and optionally a reply-to address. Therefore the type of the input for macro 'h' is (to+,sep,#PCDATA). The typed macro definition is:
(to+,sep,#PCDATA) <def macro='h'>
   <header>
      <f/>
      <par/>
      <subject><par p='2'/></subject>
      <reply-to><me/></reply-to>
   </header>
</def> 
An additional element of the macro language handles attributes. The value of an attribute can be set by an attribute in the macro call. The macro 'test' creates an element 'style' with the attribute 'color'. The value of 'color' is the value of attribute 'col' of the macro call.
EMPTY <def macro='test'>
   <style color='$col'>Lisa Simpson</style>
</def> 
For example, the macro call
<test col='yellow'/> 
will produce
<style color='yellow'>Lisa Simpson</style>.  
A possible document instance with the unexpanded macros 'family' and 'h' might look like:
<?xml version="1.0" encoding="L1"?>
<!DOCTYPE email SYSTEM "Email.dtd">
<!-- open file MailMacros.xml       -->
<!-- and read the macro definitions -->
<?UsePackage MailMacros.xml?>
<!-- begin mail                     -->
<email>
     <h><family/><sep/>Radioactive Man</h>
     <body>
         None of the new superheroes can hold a candle 
         to "Radioactive Man".
     </body>
     <signature>
         Ay Caramba! 
     </signature>
</email>
<!-- end mail                       --> 
The call of macro 'h' uses <sep/> to separate the two input forests. The macro processor expands the document to:
<email>
    <header>
        <from>bart@springfield-elementary.edu</from>
        <to>homer.simpson@snpp.com</to>
        <to>marge@freemail.org</to>
        <to>lisa@freemail.org</to>
        <subject>Radioactive Man</subject>
        <reply-to>bart@springfield-elementary.edu</reply-to>
    </header>
    <body>
        None of the new superheroes can hold a candle 
        to "Radioactive Man".
    </body>
    <signature>
        Ay Caramba! 
    </signature>
</email> 
In addition the processor extends the original DTD. In this generated DTD the macros are used as normal elements. Macro 'h' for example produces a tree of type 'header'. It follows that 'h' can be used in every context where 'header' can be used.
<!ELEMENT email     ((header|h),body,signature) >
<!ELEMENT header    ((from|f),(to+|family),cc*,subject,reply-to?) >
<!ELEMENT from      (#PCDATA|bart)* >
<!ELEMENT to        (#PCDATA|bart)* >
<!ELEMENT cc        (#PCDATA|bart)* >
<!ELEMENT subject   (#PCDATA|bart)* >
<!ELEMENT reply-to  (#PCDATA|bart)* >
<!ELEMENT body      (#PCDATA|bart)* >
<!ELEMENT signature (#PCDATA|bart)* >
<!ELEMENT sep       EMPTY >
<!ELEMENT bart      EMPTY >
<!ELEMENT f         EMPTY >
<!ELEMENT family    EMPTY >
<!ELEMENT h         (#PCDATA|sep|to|bart)* > 

With this DTD it is possible to validate a document with unexpanded macro calls. A document conforming to the extended DTD then is guaranteed to be expanded into a document which conforms to the original DTD.


T. Perst (perst@in.tum.de)