Experimenting with the Circus Language for XML ... - CiteSeerX

1 downloads 0 Views 75KB Size Report
John Coltrane?

.

Emmanuel

. . . Figure 1: Input and output mails for the reply transformation and the following filter is able to ...

Experimenting with the Circus Language for XML Modeling and Transformation Veronika Lux

Xerox Research Centre Europe 6 chemin de Maupertuis 38240 Meylan FRANCE

Xerox Research Centre Europe 6 chemin de Maupertuis 38240 Meylan FRANCE

Xerox Research Centre Europe 6 chemin de Maupertuis 38240 Meylan FRANCE

[email protected]

[email protected]

vion−[email protected] ABSTRACT

After a brief introduction to the Circus programming language, we present a simple type set to model XML structures. We then describe a transformation that takes a mail as input and produces a reply, showing how subtyping is used in order to refine the type control and specialize the transformation. Conclusions are drawn both on our (easy to use but clearly limited) XML data model and on Circus itself ; expected qualities of the language are verified ; the need for some new features is expressed. Finally, we sketch some language extensions, a richer model for XML structures, and explain our choices and expectations.

Categories and Subject Descriptors D.3.3 [Programming Languages]: Language Constructs and Features—Data Types and Structures,Polymorphism; E.1 [Data]: Data Structure—Records, Trees

General Terms Algorithms,Design

Keywords Typed Document Transformation, Document Model, XML, Programming Language, XSLT, Circus

1.

INTRODUCTION

Steele’s paper “Growing a language” [7] is a good explanation of the difficulty of designing programming languages, in particular their abstraction level. General purpose languages should propose a limited number of built-in abstractions (data and control), and specialized languages should propose more specific abstractions that simplify (and help to verify) the most common operations. XSLT[2] and XQuery[1], some of the transformation solutions from the W3C are specialized in XML document transformation, ∗in partnership with INRIA Rhones-Alpes, projet OPERA

Emmanuel Pietriga



Jean-Yves Vion-Dury

and therefore offer specific and abstract data and execution model. They are ”sharp”, i.e. well adapted to solve a restricted class of problems, but might become very cumbersome when used for solving problems which slightly escape the initial focus. For instance, dynamic and contextual transformations such as the ones found in transcoding might require managing various information flows with complex time requirements ; even simpler, solving (some) hyperlinks during a transformation may introduce delays that are better mastered thanks to a multithreaded infrastructure. XDuce [6] offers a specific data model based on tree grammars with explicit typing and powerful subtyping mechanisms, and a (restricted) functional execution model. This language embeds matching a` la ML, enriched with tree regular expressions. We believe the XDuce typing approach to be very promising, because typing is a very natural way to guarantee (some of) the structural constraints required for XML document delivery. Moreover, we also identified subtyping as a solution for handling various levels of control over structural constraints. After a brief presentation of Circus’ design principles, we report on our first experiments and explain how we extended the language toward more relevant XML processing and modeling.

2.

THE CIRCUS TRANSFORMATION LANGUAGE

Overview. Circus[4, 10, 9] is a programming language specialising in structure transformation, not specifically designed for transforming XML documents, but any kind of structured data. Circus is built upon a formal calculus that defines the (smallstep) operational semantics of (i) structural filtering operations, (ii) composition algebra (iii) various operations, control statements and concurrent execution based on a Linda-like [5] communication model. The later relies on a central coordination memory on which processes can write, read or consume values1 . We briefly summarize here some of the most relevant features of Circus.

Types. Circus features a strong type system which handles primPermission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. DocEng’02, November 8–9, 2002, McLean, Virginia, USA. Copyright 2002 ACM 1-58113-594-7/02/0011 ...$5.00.

itive data types (e.g.Boolean, String, Integer, Float, None, Unit), structured types (e.g. Multiset, Sequence, Tuple, Record, Dictionary), enumerated types, recursive types and operations on types such as union and intersection. This type system enables data modeling, precise static type checking and subtype polymorphism. 1 Concurrent programming in Circus won’t be described in this paper.

Circus is characterized through an important property of the type system, the ”type soundness” (subject reduction and progress theorem) which says that a well typed expression cannot produce execution errors - under strong execution hypotheses, such as infinite memory2 .

pam x : t1 , y : t2 .e, where x is the input parameter, y the output parameter (always initialized with the default value of type t2 ), and e is a Circus expression of type Unit, i.e. an imperative expression. A PAM implicitly returns the output variable when execution is finished. The following PAM

Rules, action systems. Circus rules have either the form b ⇒ e

pam x : String, y : String.( x # ? ++ (((%0 /0 or %0 −0 ) ++ ?a) and ?b) ⇒ y := a + b )

where b is a boolean expression and e any expression, or e1 #f ⇒ e2 , where e1 is any valid expression computing a value (subject), f any filter with a type compliant with e1 and e2 any other expression, including rules. Informally, such a rule evaluates the subject e1 and tries to apply the filter f . If this operation succeeds, e2 is evaluated in the possibly modified context (filters can indeed extract information from the subject and store it in variables). If the operation fails, the value none is returned (none is a distinguished value of type None). Rules can be executed in sequences as any other imperative constructs (general form e1 ; e2 ), cascaded or combined in action systems [|e1 , . . . , ek |] that execute ei in order until a value different from none is found.

Filters. Filters are mainly used in the left-hand side of rules of

returns ’xml-xml’ if invoked for instance with ’circus-xml’ as argument.

Abstraction level. Circus is at a lower abstraction level than XSLT but higher than a scripting language (such as Perl or Python) associated with a DOM/SAX compliant library. Like many other languages, Circus is adapted to markup processing through a library of components, type structures, basic components and tools.

3.

the form : expression # f ilter => action that read “If expression matches filter then do action”. Filters are made of: 1. basic filters such as ? (existence check), %e (evaluates e and checks if equality holds) and ?x (checks existence and assigns to the variable x). This last may involve runtime type checking if the variable x is already defined in the environment with a given type, and if the static type checking is not able to infer conformance. New variables can be introduced by filters (their type is inferred) with a scope restricted to the right-hand side expression of rules in which filters are used. 2. constructed filters, built using a symmetry principle: terms, filters (and also types) use similar notations. For instance, record terms have the form hm1=e1 , . . .i, filters hm1=f1 , . . .i and types hm1 : t1 , . . .i. Sequences are built respectively by [e1 , . . .], [f1 , . . .] and [t]. 3. combinators, which allow flexibility. The most important (aggregation) has the form f1 ++ f2 and applies to strings, sequences, multisets and dictionaries; it is considered as the dual of the concatenation operator +. As an example, [1, 2, 3] # [%1] ++ ?x => x evaluates to [2, 3], and ’circus/xml’ # ? ++ %0 /0 ++ ?x ⇒ x evaluates to 0 xml0 . Other combinators f1 and f2 , f1 or f2 have the expected semantics (see example below).

Polymorphic Abstract Machines (PAM). are the basic transformation units of Circus. A PAM is a kind of procedure with one explicitly typed input and one output parameter3 . The syntax is 2 Some other properties, like completness and soundness of type checking algorithms are still under consideration, as the language recently evolved toward significant extensions such as references, record with restricted polymorphism, explicit type extension, and intersection operators. 3 PAM have strong compositional capabilities but the PAM composition algebra won’t be described here.

MODELING AND TRANSFORMING XML STRUCTURES IN CIRCUS : FIRST EXPERIMENTS AND LESSONS LEARNED

This section presents our first model of XML structures in Circus. It is a simplified model in which some aspects of XML are lacking (e.g. namespaces). Though, it proved interesting for experimenting with Circus and allowed us to write quite complex transformations (see the MathML content to presentation transformation in [8] written in both XSLT and Circus).

3.1

Example 1: Basic XMLTree type and simple transformation

Defining the Circus XMLTree type. XML nodes are modeled through a recursive record type called XMLTree, in which the label field contains the name of the node, the sub field contains an ordered sequence of sibling nodes and the attr field contains a dictionary of attribute/value pairs. Leaves of such trees can be strings (P Cdata and Cdata), comments (XM Lcomment), processing instructions (XM Lpi), or empty elements (no sub field). This is expressed in Circus with the following type definitions : type Cdata = hcdata : Stringi type XMLcomment = hcomment : Stringi type XMLpi = hpi : htarget : String, instructions : Stringii type PCdata = String type XMLTree = hlabel : String, attr : {String : String}, sub : [XMLTree]i |hlabel : String, sub : [XMLTree]i |hlabel : String, attr : {String : String}i |hlabel : Stringi |Cdata | XMLpi | XMLcomment | PCdata type XMLForest = [XMLTree]

A compliant tree instance is for instance given by : Mail : XMLTree = hlabel=’mail’, attr={’ref’=’m1’}, sub=[hlabel=’date’, sub=[’26-01-2201’]i]i

26-01-2001 [email protected] [email protected] Jazz

Hello Jean-Yves,

Have you listened to My Favorite Things by John Coltrane?

Emmanuel



26-01-2001 [email protected] [email protected] Re: Jazz

In your message sent on January 26, you wrote:

Hello Jean-Yves,

Have you listened to ’My Favorite Things’ by John Coltrane?

Emmanuel



Figure 1: Input and output mails for the reply transformation and the following filter is able to check the corresponding structural constraints and to extract the date element’s content: hlabel=%0 mail0 , sub=[hlabel=%0 date0 , sub=[?s]i] ++ ?i This filter is constructed similarly to values and is composed of sub-filters such as %’mail’ which checks if the name of the root node is ’mail’ and ?s which stores the content of date into variable s. [· · · ] ++ ? states that date must be the first element in the sequence of children and can be followed by other elements. Similarly ? ++ [· · · ] would express that date must be the last element in the sequence with zero or more other elements before and ? ++ [· · · ] ++ ? that date can be anywhere in the sequence.

Transforming XMLTree instances. Figure 1 shows input and output examples of a transformation that prepares a reply to a mail document (input document conforms to the DTD in Figure 2). The transformation produces a mail, with fields date, sender, recipient, subject and body. Content of the new date element is provided by a T oday() function. Subject’s content is the same as in the input, inserting “Re :” at its beginning if necessary. Finally, the respective contents of elements sender and recipient are inverted. The transformation is performed by a PAM named reply which explores the input forest through a top-down depth-first traversal. This procedure is both iterative (it scans the input sequence and successively process each element) and recursive (it invokes itself on its sub member if any). const reply : [ XMLTree ] =⇒ [ XMLTree ] = pam x : [ XMLTree ], y : [ XMLTree ] var s : String.( ∗( x # [? tree ] ++ ? x => [| /*R1*/ tree # h label= % ’mail’ , attr={ref=?aRef} , sub=?sT i ⇒ y+= [h label=%’mail’ , attr={ref=’r-’+aRef} , sub=reply(sT) i], /*R2*/ tree # h label=%’date’,sub=[?s] i ⇒ y+= [h label=’date’, sub=[Today( )] i], /*R3*/ tree # h label=%’recipient’,sub=[?s] i ⇒ y+= [h label=’sender’,sub=[s] i], /*R4*/ tree # h label=%’sender’,sub=[?s] i ⇒ y+= [h label=’recipient’,sub=[s] i],

< !ELEMENT mail (date,recipient,sender, subject,textbody)> < !ELEMENT date (#PCDATA)> < !ELEMENT recipient (#PCDATA)> < !ELEMENT sender (#PCDATA)> < !ELEMENT subject (#PCDATA)> < !ELEMENT textbody (p+)> < !ELEMENT p ( #PCDATA | cite)*> < !ELEMENT cite (#PCDATA)> < !ATTLIST mail ref CDATA #REQUIRED >

Figure 2: DTD for mail documents /*R5*/ tree # h label=%’subject’,sub=[(%’Re:’++?s ) or ?s ]i ⇒ y+= [h label=’subject’,sub=[’Re:’+s] i], /*R6*/ tree # h label=%’cite’,sub=[?sT] i ⇒ y+= [” + sT + ”], /*R7*/ tree # h label=?aL, sub=?sT i ⇒ y+= [h label=aL , sub=reply(sT) i], /*R 8*/ y+= [ tree ] |]) Rule R1 selects a mail element and extracts its children in variable sT ; it creates a mail element whose children are the result of applying the transformation rules to sT. With rules R3 and R4, sender and recipient are copied from the source and inverted. The subject element is copied in the output either by just copying the source content if it was already beginning with ’Re:’ or by adding ’Re:’ to its content if missing (rule R5). Rule R6 copies the content of cite elements, surrounding these by quotes. Therefore, there are no cite elements in the output : the paragraphs only contain PCDATA. Rules R7 and R8 can be considered as default rules : elements with a sub field are copied in the output and the PAM is recursively applied on their children, other elements simply being copied in the output.

Observations. These first XML modeling and transformation experiments using Circus allowed us to check some of the language’s qualities. In particular : • The syntactic symmetry between filters used in the left-hand side and constructors used in the right-hand side helps memorizing the language and often makes transformations more readable, • Filtering in Circus is homogeneous : matching applies both

on elements (i.e. the XML structure) and on the content (i.e. PCData) (see the rule R5 above as an example). It would therefore be easy in Circus to transform citations between quotes into citations contained in cite elements (i.e. the reverse of rule R6, which corresponds to something that is difficult to do in XSLT), • Type checking is precise and helps preventing many errors at compile time, • The forest-based traversal is powerful and flexible. In this example, both input and output parameters are of type XMLForest. Typically, the transformation is invoked on a (onetree) forest that contains the result of the input mail parsing. Interestingly, this kind of transformation enables us to handle “semi-structured” data, for instance documents that have been partially linearized by a previous transformation. In this case, the already processed part (a leaf of type string) transparently goes through the processing, while the rest of the document, still structured, is potentially processed. We believe that this approach can be useful for handling incremental transformations where several top-down traversals are required in order to compute a linearized final form.

3.2

Example 2 : A more complex transformation

Now, we want the output textbody element to include a quotation of the input textbody content. More precisely, the quotation must be enclosed in a paragraph with the text ”In your message sent on ”+ Month + Day +” you wrote:” where Month and Day are taken from the date element. This can be achieved by changing R1 to :

3.3

Example 3 : Modeling and transforming email with sub-types of XMLTree

Email as a specialized sub-type of XMLTree. Our XMLTree type models all XML document instances. But Circus subtyping allows us to better capture document models which comply to particular Schemas. For example, in the XMLTree type all element embeddings are legal whereas in Xmail, a sub-type of XMLTree defined below, only mail, date, recipient, sender, subject, textbody, p, cite are legal. XMLmail’s definition is almost the same, but label elements are defined by an enumerated string subtype called mailLab instead of the more general type string. type mailLab = String in { ’mail’,’date’,’recipient’, ’sender’,’subject’,’textbody’,’p’, ’cite’ } type XMail = h label:mailLab, attr: {String : String}, sub : [ XMail ]i | h label:mailLab, sub: [ XMail ]i | h label:mailLab, attr: {String : String}i | h label:mailLab i | Cdata | XMLpi | XMLcomment | PCdata

Yet, the DTD in Figure 2 tells more than this: in particular, it defines the legal nesting of elements. To model this as best as possible, we define the XMail type as follows :

where msg is a simple lambda function that constructs a sequence of one string:

type XMail = h label: String in { ’mail’ }, attr: {String in { ’ref’ } : String}, sub: [ XMLdate | XMLrecipient | XMLsender | XMLsubject | XMLtextbody )]i type XMLdate = h label: String in { ’date’ }, sub: [ PCdata ]i type XMLrecipient = h label: String in { ’recipient’ }, sub: [ PCdata ]i type XMLsender = h label : String in { ’sender’ }, sub : [ PCdata ]i type XMLsubject = h label : String in { ’subject’ }, sub : [ PCdata ]i type XMLtextbody = h label : String in { ’textbody’ }, sub : [ XMLp ]i type XMLp = h label : String in { ’p’ }, sub : [ PCdata | cite ]i type XMLcite = h label : String in { ’cite’ }, sub : [ PCdata ]i

const msg := lambda month: String. lambda day: String. [ ”In your message sent on ”+month+”, ”+day + ” you wrote :” ]

Observations. This type definition is equivalent to the DTD for

tree # h label = %’mail’ , sub =? ++ [h label=%’date’,sub= [ ?date ]i] ++ ?sT1 ++ [h label=%’textbody’,sub=?sT i] ++ ?i ⇒ date # ?day ++ %0 −0 ++ ?month ++ %0 −0 ++ ? ⇒ y += [h label=’mail’ , sub= [h label=’date’,sub=[Today( )] i] + reply(sT1) + [h label=’textbody’, sub= [h label=’p’,sub=msg(month)(day) i] + reply(sT) i] i]

Observations. This rule looks more complex than the previous ones. In fact, the encoding of the transformation is constrained by the fact that only the descendants of the current node are accessible. Therefore when several elements in the source are needed simultaneously to build the output, they have to be matched from an upper common node in the tree hierarchy. This may lead to less readable rule systems because complex filters are necessary to describe the structure that includes the various required elements and their common ancestor. Developing transformations showed us how Circus and the proposed XML model influence developers w.r.t how they design and write their transformations in a pure top-down way, which is often very different from how they would have done it using XPath+XSLT and axes like parent and ancestor. Programmers can miss the “XPath+XSLT way”, especially when writing “target driven” transformations. This observation holds for all “functional” approaches, because tree traversal is directly associated with recursive execution schemes.

mail documents, except for the ordering constraints, as these cannot be expressed in the current version of Circus4 . Using traditional tree-based lists instead of linear sequences, as often found in functional languages would allow such control, but would also make filtering very cumbersome. So one clear request that emerged from our evaluation is to include typing mechanisms able to capture such ordering constraints (ordering of elements, optional elements, etc.) in the definition of sequences.

Transforming XMail. Particularly interesting is the relationship between the type hierarchy and the PAMs that process instances of types and subtypes. Of course, the reply PAM defined above can handle input trees of type XMail as it is a subtype of XMLTree. But, using the previous transformation, we do not take advantage of the type control provided by the XMail subtype on both input and output structures. As an illustration, the equivalent solution below makes better use of the typing information: 4 Note also that a strict equivalence would require for instance allowing comment nodes as leaves in various parts of the tree.

const reply := pam x:XMail, y:XMail .( x.sub # ?subTrees ⇒ ∗( subTrees # [? node ] ++ ?subTrees ⇒ ( [| node # h label=%’date’ i ⇒ y.sub+= [h label=’date’,sub=[Today() ]i], node # h label=%’recipient’ i ⇒ y.sub+= [h label=’sender’,sub=node.sub i], node # h label=%’sender’ i ⇒ y.sub += [h label=’recipient’,sub=node.sub i], node # h label=%’subject’,sub=[(%’Re:’ ++ ?s ) or ?s ]i ⇒ y+= [h label=’subject’, sub=[’Re:’ + s] i], node # h label=%’textbody’ i ⇒ y.sub+= [h label=’textbody’ , sub=replyBody(node.sub) i] |]))) const replBody := pam x:[XMLp], y:[XMLp] .( ∗( x # [? aP ] ++ ? x => [| aP # h label=%’cite’, sub=[?sT] i ⇒ y+= [”0 ” + sT + ”0 ”], y+= [ aP ] |]))

Observations. The transformation has now been specialized for the XMail subtype. In particular, the output of reply is of type XMail and hence its linearisation will produce a valid document (up to the limitations mentioned above).

4.

TUNING THE CIRCUS LANGUAGE FOR XML

First experiments with complex transformations in Circus and their evaluation allowed us to identify some limits of our first solution. We identified desirable features of a richer model capable of capturing more precisely structural constraints expressed in the schemas associated to document classes. This led to the evolution of Circus, both towards the enhancement of the type system and towards the addition of new programming constructs.

4.1

More precise document type control

The main evolution of the type system was made in order to allow capturing constraints on the number of occurrences and on the ordering of elements in sequences, as expressed in the right-hand side of DTD rules like the following :

We studied a regular expression formalism and implemented a typing mechanism that allows the modeling of such constraints. The corresponding syntax is given by (t denoting the syntactic category of types (Int, String, . . .)): t → [s] s → s, s | s|s | s&s | s{m, n} | s∗ | s+ | s? | (s) | t where s1 &s2 = (s1 , s2 )|(s2 , s1 ) and where 0 ≤ m ≤ n and s{m, n} = sm | · · · |sn (sk denotes as usual k repetition of s). The above rule would be captured with the type : h label:String in {’div1’}, sub:[head,(p | list | note)*, div2*] i Thanks to this enhanced type system, it will be possible to generate more precise specializations of the general XML type reflecting the constraints of a given document class, based on its associated DTD or XML Schema. The use of these refined types can have several advantages, among which the possibility to create transformation programs statically guaranteeing the validity of the target

documents w.r.t the schema constraints captured by our model5 . Furthermore, these types being subtypes of the more general type XT ree, transformation components written for this later type can also be applied to its specializations.

4.2

Richer transformation model

We wanted to enrich the transformation model so as to allow any tree traversal strategy and to give direct access to nodes. In particular, the Circus language should enable programmers to write both source driven transformations (based on recursive descents) and target driven transformations. To achieve this goal, the main evolution consisted in introducing references in Circus. Thanks to references, the basic XML tree model can be extended toward more powerful structures at a reasonable programming cost, for example adding a backward link (i.e. nodes have a link to their father node), so that traversal can be done upward if required. Attributes are no longer stored in dictionaries but as references in sequences. type XElem = hlabel : String, father : (None|ref XElem), sub : XForesti | hlabel : String, father : (None|ref XElem), attr : [(ref XAttr)∗ ]i | hlabel : String, father : (None|ref XElem), sub : XForest, attr : [(ref XAttr)∗ ]i | hlabel : String, father : (None|ref XElem)i type XPCData = hpcdata : String, father : (None|refXElem)i ··· type XTreeNode = ref (XPCData | · · · | XElem) type XAttr = h name : String, value : Stringi type XForest = [XTreeNode∗ ] type XNode = XTreeNode|ref XAttr Furthermore, we wanted the Circus filters to provide an expressive power equivalent to XPath expressions, since, as observed above, the XPath language (already familiar to many programmers) provides very good abstractions for expressing node selection and will probably play an increasing role in XML processing. To achieve this goal, we define recursive filters that in particular allow matching descendants at any depth. In addition, because the compactness of XPath expressions is very attractive, we plan to integrate this sub-language through two dedicated primitives, xpathMatch and xpathSelect. These built-in functions will accept an XPath expression as a string and return a function that executes the operation on an input tree. For example, the result of : xpathMatch(0 //p/cite0 ) shall be : pam x : XNode, y : Bool. (!x # h[label = %0 cite0 , father = ref h[label = %0 p0 ]i]i ⇒ y:=true)

5.

CONCLUSION

In this paper, we have introduced Circus, a programming language specialized in structure transformations. Circus is well-suited but not limited to XML document manipulation, and can be seen as an intermediate solution between XSLT and lower-level approaches such as DOM+Java. We primarily focused here on the modeling and manipulation of XML documents, presented a first modelling in Circus and identified some of its limits. Finally, we have sketched the evolution of Circus both towards the enhancement of 5 Some constraints are not captured by our model and can only be verified at runtime, like the uniqueness of ID attributes.

the type system and towards the addition of new programming constructs. Circus version 2.0 alpha compiler will soon be available under binary form on the AlphaAvenue site [11] with documentation and various components among which tools for translating DTDs into Circus types. Beside experimental work, XPath extensions such as described above will be studied, and we plan to explore complex transformation architectures suitable for handling ’on-the-fly’ contextual transformations of Internet documents [3].

6.

REFERENCES

[1] D. Chamberlin, D. Florescu, J. Robie, J. Simeon, and M. Stefanescu. Xquery: A query language for xml, February 2001. http://www.w3.org/TR/xquery. [2] James Clark (Editor). Xsl transformations (xslt) version 1.0 w3c recommendation, 16 November 1999. http://www.w3.org/TR/1999/REC-xslt-19991116. [3] XRCE (Xerox Research Center Europe). Contextual computing, 2002. http://www.xrce.xerox.com/competencies/contextualcomputing. [4] XRCE (Xerox Research Centre Europe). Circus home page, 2002. http://www.xrce.xerox.com/competencies/contextualcomputing/circus.

[5] D. Gelernter and L. Zuck. On what linda is: Formal description of linda as a reactive system. In LNCS, editor, Proceedings of the Second International Conference on Coordination, Languages and Models (Coordination’97), Berlin, Germany, volume 1282, pages 187–204, September 1997. [6] Haruo Hosoya and Benjamin C. Pierce. XDuce: A typed XML processing language (preliminary report). In WebDB (Informal Proceedings), pages 111–116, 2000. [7] Guy L. Steele Jr. Growing a language. OOPSLA’98, October 1998. http://cm.bell-labs.com/cm/cs/who/wadler/steeleoopsla98.ps. [8] E. Pietriga. Mathml content to presentation transformation, December 2000. http://www.inrialpes.fr/opera/people/ Emmanuel.Pietriga/mathmlc2p.html [9] E. Pietriga, V. Quint, and J.-Y. Vion-Dury. Vxt: A visual approach to xml transformations. In ACM, editor, Proceedings of the ACM Symposium on Document Engineering, Atlanta, USA, November 2001. [10] Jean-Yves Vion-Dury. Circus: un g´en´erateur de composants pour le traitement des langages visuels et textuels. Doctorat d’informatique, Universit´e Joseph Fourier, Grenoble, June 1999. Confidential status. [11] Rochester Institute of Technology Xerox, PARC. Alphaavenue (http://www.alphaavenue.com), 2001.