|
JavaScript XML Tag Object |
||||||||||||||||||||||||||||||||||
How XML data is processed.Before you can understand the tag tree that has been generated you need to understand a little about how the presentation engine puts pages together. Page generation is a two stage process:
Stage 1: Executing the XML Tree.Stage one builds the tree. The resulting tree is represented in the following diagram: This generates an internal representation of the tree. Each of the nodes within the tree has some associated behaviour that has yet to be executed, this behaviour is determined by the name of the tag. (Generally the behaviour of a tag when it is executed is to generate its output representation that will be sent to the browser. How it does this is down to that specific tag). Stage 2: Executing the XML Tree.The presentation engine takes the root of the XML tag tree and executes it in order to generate the page it will ultimately send to the browser. Each node (XML tag, text, comment etc) has an 'output' area associated with it. In general the intention is for each node to set its output area to be the text it wants to send to the browser. For example for a simple text element the default behaviour is to set the text element's output area to be the same as the text it contains. Whether or not the text gets eventually output depends on what the node'sparent wants to do. This behaviour is either defined 1) as default behaviour by the Whitebeam system or 2) the default behaviour can be overridden by the developer by using the <rb:macrotag> facility or 3) a user defined tag can have its behaviour specified by the developer by using the <rb:macrotag> facility. A simple HTML tag like the paragraph marker <p> will generate its output by executing each of its children and then concatenating the output from each of those into its own output area. Consider the following example: The paragraph tag is in the process of being processed. It's behaviour is to execute each of its children. The child XML tags in this example are all standard XHTML mark-up. The behaviour of these tags it to recursively process their children then concatenate their output along with their own wrapper. Conside the <i> tag (marked [1] in the diagram). This has executed its child - a simple text element. The output area of the text element has been set to the contents of the text field : "Some Text in bold-italics". The <i> tag then sets it's output area to be the concatenation of all it's children - wrapped in <i> and </i>. This happens all the way up the tree. The diagram illustrates the contents of the output areas for each XML element after all the children of the paragraph [2] have been executed but before the paragraph has generated its own output. You can see that to generate the contents of its own text area the paragraph element simply concatenates the contents of its own direct children - wrapping them in a <p> and </p> . Special Behaviour.The behaviour described above is the default behaviour for a standard HTML formatting tag. Many of the Whitebeam tags generate their output in different ways. It is important to realise that how a tag generates its output - and how it makes use of any of its children is entirely at the discretion of that element. The following is a brief description of how a couple of special Whitebeam tags generate their output.
The 'rb:block' tag is a very good example of how tags choose to execute - or not - their children. In the case of the block tag - its implemetation is to not execute those children. So, what is the point of it? See below... Manually Executing XML SubtreesThe XmlTag class represents a portion of the XML document tree - as returned from rb.page.tagtree. The text() and bodytext() methods of XmlTag access the output area of the tag. But at any time the output area may contain different things:
You can see from the description of the rb:block tag above that initially the output areas of all children of the block will be empty. In JavaScript you can however get hold of the sub-tree of the rb:block tag and execute it. To do this give the block tag an id (using the rb:id attribute). This is illustrated below:
This example block is labeled - so we can find it - with the name "myBlock". Note that thie block contains the necessary HTML for a single row in a table. We can now get this code subsequently in an <'rb:script...> tag using the rb.page.tagtree method and specifying 'myBlock'.
Remember at this stage these tags have never been executed! If you now call 'var text=tag.bodytext()' the result will be an empty string. To generate output you have to first execute the tag. Do this using the tag.regenerate() method. The normal behaviour of this method is to run the tag on which it is invoked. An exception occurs where the tag is an 'rb:block' tag - because the effect of that tags execute is to do nothing! In the case of an rb:block tag all of the children of the tag are executed. This will effectively populate the output areas of each of the children. Note that in the example above the block contains active server-side behaviour in the form of <rb:eval...> tags. The block can be used in a loop to dump the contents of an object's properties:
Implementing XML Macros (rb:macrotag)The tag processing can be used extensively in implementing your own specialised tags - or in providing translations from one XML format to another. In this case the macro itself is defined using the rb:macrotag tag. This declares a new tag, the name being defined by the 'name' attribute of that tag. If the 'name' attribute of the macrotag is the same as an existing, default tag (such as 'body'), the Presentation Engine will execute the behaviour defined by the macro instead of the default behaviour. The Presentation Engine implementation of the rb:macrotag tag creates an internal representation of the named tag and then stores the JavaScript implementation against that tag. When the engine subsequently finds an instance of the new tag in the document it calls the JavaScript implementation for that tag. The implementation can use the XmlTag classes and the rb.page.tagtree method to access the body of the tag. As with the rb:block example, the engine does NOT automatically execute the body of the macro - to do so would reduce the scope of the JavaScript implementation. So to get the body text of the tree your must first execute the tree using tag.regenerate(). This does of course give the JavaScript implementation of the tag the freedom to only execute a portion of the body tags. Consider an example implementation of a tag called '<switch...>' that we want to provide. This will take a number of child tags - <case...>. We'd use this as follows:
This is similar to the JavaScript 'switch' statement - but executed in tags. This illustrates why the Presentation Engine does not automatically execute trees under macro implementations or block tags. The implementation of <switch...> will search through the list of provided cases and only execute the one that matches the result code. This means that only one of the redirection tags will be executed. A more complete example of how to use rb.page.tagtree and the rb:macrotag tags can be found in the Whitebeam examples. Building an XML tree from source.So far this paper has discussed manipulating parts of the XML tree of the current document, or of another document built into the current one using <rb:include...>. Another case to consider is where the application is given a set of XML source code and wants to manipulate the underlying XML structure. Possible examples are:
The Presentation Engine allows 'on-the-fly' compilation of some XML source code using the rb.page.buildxml method. The method takes a string - assumed to contain XML - and parses it to build an XML tree. The resulting tree is then appended to the tag tree as a child of the currently executing child. Note that commonly, the currently executing child is an instance of the rb:script tag. A script tag usually contains exactly one child element - a text item - that contains the server-side JavaScript to be executed. After executing rb.page.buildxml, the script tag will contain 'n+1' elements, where 'n' is the number of XML tags successfully extracted from the XML source. These elements will be indexed 1 through 'n'. This situation is illustrated in the diagram below. Note that running rb.page.buildxml is accumulative. In the diagram, if the string were executed again, the rb:script tag would acqiure two new XML child tags. To manipulate the resulting XML tree the author must first find it and get a JavaScript representation of it. You find the tree by using the rb.page.tagtree method. Generally you will get the tag of the executing node then search its children for the appropriate node.
ExampleThe following simple example shows a JavaScript recursive function that gets the tag tree for the XML tag called 'root' (a dummy table) and then provides a summary of the tree in the web page output.
|
|||||||||||||||||||||||||||||||||||
Whitebeam release 1.3.36 (loadtime : 8ms) |