Page Modification

Page modification is an important part of the WebL markup algebra. As we have seen already, the attributes of markup elements can be elegantly modified by accessing the fields of pieces. This section will focus on how to insert pieces into a page, delete pieces from a piece, and replace pieces of a page.

Creating Pieces

There are several ways to create new pieces (See See Page Modification Functions). After a new piece has been created, it can be inserted into a page at a specific position. We already introduced the NewPage function which takes a string and a mimetype as argument, and returns a page object. We also know that then applying the Content function to a page returns a piece covering the whole page. In fact, the code to create a piece in this manner:

Content(NewPage("<html> ... </html>", "text/html"))

 

occurs so often that we also use the following short-hand:

NewPiece("<html> ... </html>", "text/html")

 

Another way of creating a new piece is to pass the begin tag and end tag of two arbitrary pieces to the NewPiece function (See Application of the NewPiece function). The function returns a new unnamed piece with new unnamed tags inserted just before and after the begin tag and end tag respectively (to "wrap" its contents). The NewPiece function will also wrap a piece argument in the same manner1.

The NewNamedPiece function works in a similar manner as NewPiece, except that a new piece with the indicated name is created. Seeing that any begin and end tag pair (not belonging to the same piece) can be passed to this function, programmers should be aware that invalid HTML or XML can be created where elements do not nest properly. As WebL uses a flexible internal page representation, the presence of overlapping elements does not present any problems.

Examples:

// Turn the text from the word "WebL" to the end of

// the sixth paragraph to italic.

var a = Pat(P, "WebL")[0], b = Elem(P, "p")[5];

NewNamedPiece("i", BeginTag(a), EndTag(b))

 

// Turn all occurrences of WWW to a hyperlink.

every x in Pat(P, "WWW") do

var p = NewNamedPiece("a", x);

p.href := "http://www.w3.org"

end

 

Application of the NewPiece function

 

Inserting Pieces

The functions InsertBefore and InsertAfter insert a piece into a page either before or after a specified tag. Inserting a piece p involves copying the contents of the piece and inserting the copied tags and text segments one after another at the destination point according to the following rules:

All the text segments contained in p are copied.

All the named tags contained in p are copied (also includes the named tags of p itself). Also suppose there exists a piece q that is either inside p or overlaps with p. In case q is inside p, both the begin tag and end tag of q will be copied to the destination. Otherwise, if q overlaps with p (and is not inside p), we will, according to our definition, only copy either the begin tag or end tag of q. To prevent this unfortunate situation with dangling pieces, the tag of q outside of p is also copied. In case of many dangling tags outside of p, we copy all of them, making sure that their relative ordering is preserved.

Unnamed tags contained in p are not copied.

See Copying Pieces during Inserts shows how copying piece B with an overlapping piece C after the begin tag of A, results in the copies B' and C' in the page. Note that the source page on the right top corner of the figure remains unchanged.

In case a piece set (instead of a piece) is passed to these two functions, each of the elements of the argument will be copied in sequence to the destination insertion point. Note that when the piece set contains nested elements, the nested elements will be inserted twice or more times, possibly one after another in the destination page.

Example:

// Insert an image at the beginning of each h1 tag.

var p = NewPiece("<img scr=a.gif>", "text/html");

every x in Elem(P, "h1") do

InsertAfter(BeginTag(x), p)

end

 

 

Copying Pieces during Inserts

 

Deleting Pieces

The Delete function deletes a piece from a page. In case the function is passed a piece set argument, each of the elements of the argument piece is deleted.

One of the problems we face with deletion is that some program variables might still refer to pieces that were previously deleted. Accordingly, accessing these deleted pieces through these variables might cause some problems. To simplify the problem, we define the following sematics for deletion of a piece q:

All the text segments contained in piece q are physically removed from the page. (This is not a problem seeing that we cannot refer to text segments in the WebL markup algebra.)

Unnamed tags inside q are left untouched.

The tags of named pieces completely inside p are converted to unnamed tags. They still can be referred to but essentially become invisible.

If q is named, then its tags are converted to unnamed tags.

The tags of named pieces that overlap q (but are not inside q) are left untouched.

See Deleting Pieces illustrates the situation when overlaps occur during deletions. Note how piece C remains named because its end tag is located outside and to the right of B. Of course, as we simply leave tags where they are in the page, we can imagine situations where the page fills up with unused tags after several deletions. To counter this problem, a scrubber process is periodically invoked to remove unused tags from a page (i.e. tags that are not accessible to the programmer as detected by the Java garbage collector).

Examples:

// Delete all occurrences of the word "cool".

Delete(Pat(P, "cool "))

 

// Remove all H1 and H2 headings.

Delete(Elem(P, "h1") + Elem(P, "h2"))

 

Deleting Pieces

 

Replacing Pieces

The Replace function deletes each piece in the first argument and inserts copies of the pieces of the second argument at that position. The function can be coded using Delete and InsertAfter in the following manner:

var Replace = fun(A, B)

every a in A do

Delete(a);

InsertAfter(BeginTag(a), B)

end

 

Note that this encoding is only possible because the Delete function does not remove any tags from the page, and thus we can apply the BeginTag function to a deleted tag without causing an exception.

Examples:

// Make all links bold.

links = Elem(P, "a");

every L in links do

Replace(L, NewPiece("<b>" + Markup(L) + "</b>"))

end

 

// Replace all links with the word "censored".

Replace(Elem(P, "a"), NewPiece("<i>censored<i>"))

 

 

Page Modification Functions

Function

Description

Delete(s: pieceset): nil
Delete(q: piece): nil

Deletes s or q from the page by removing all the pieces from the page data structure.

InsertBefore(t: tag, q: piece): nil
InsertBefore(t: tag, s: pieceset): nil

Inserts a copy of q before the tag t. Inserts copies of the elements of s before the tag t.

InsertAfter(t: tag, q: piece): nil
InsertAfter(t: tag, s: pieceset): nil

Inserts a copy of q after the tag t. Inserts copies of the elements of s after the tag t.

NewPiece(t1: tag, t2: tag): piece

Returns a new unnamed piece starting before t1 and ending after t2.

NewPiece(q: piece): piece

Equivalent to NewPiece(BeginTag(q), EndTag(q))

NewNamedPiece(name: string, t1: tag, t2: tag): piece

Returns a new named piece starting before t1 and ending after t2.

NewNamedPiece(name: string, q: piece): piece

Equivalent to NewNamedPiece(name, BeginTag(q), EndTag(q)).

Replace(a: pieceset, b: pieceset): nil

Replaces each piece set of a with copies of all the elements of b.

 


1. Technically the function does not modify the contents of a page because only unnamed tags are inserted into the page.


Up Previous Next