Re: Global Variables and JADE vs OMNIMARK

Subject: Re: Global Variables and JADE vs OMNIMARK
From: Brandon Ibach <bibach@xxxxxxxxxxxxxx>
Date: Tue, 8 Dec 1998 03:01:27 -0600 (CST)
Mike Sosteric said:
> 
> I've been walking around for hours and I can't seem to get it. I seem
> to be able to down the grove easy enough (process-first-descendant,
> (select-elements (children (current-node), etc.  but I can't seem to
> go up. I'm gonna bug you for more help. I hope you don't mind.  I have this
> partial doc instance ...
> 
> <IXML>
>  <HEAD>
>   <DESCRIPTION><TITLE>THE TITLE</TITLE></DESCRIPTION>
> </HEAD>
> <BODY> ...</BODY>
> 
> I've tried a bunch of different examples and I won't bore you with the
> broken code. But the key is probably understanding what this does
> 
> (define (get-publisher-name node)
>   (let ((gr (node-property 'grove-root node)))
>     ; do navigation magic here
>   ))
> 
> what does "gr" mean here. I tried sticking that inside (parent (gr))
> thinking it was a node but it is not because that doesn't seem to
> work. I've also tried working with (node) but that hasn't got me above
> the level of <BODY>
> 
Hi, Mike...
   First of all, let me just lay a little groundwork, to make sure
we're on the same page.  A grove doesn't really map to your input
document as one-to-one as you might think.  A node in a grove is not
always an element.  For purposes of SGML/XML, a node in a grove can
represent a number of different things, from the entire document
(which is what the "grove root" node generally represents), to an
element, to an attribute of an element, to an individual character in
the text of an element.
   A node has a "class", which defines what type of object it
represents, and a list of "property" assignments, which are name/value
pairs, much like XML attributes.  Which properties a given node has is
determined by its class.  Some of these properties are simple values,
like a string.  For instance, a node of class "element" has a property
called "gi" which is a string value representing the generic
identifier (or tag name) of the element.
   A property can also be a list of one or more other nodes in the
grove.  For instance, the element node representing the <TITLE> from
your example above would have a property called "content", which would
be a list of nine nodes, all of the "data character" class,
representing the text of the title.
   So, on to the code snippet.  In this definition, "node" represents
the node list which is passed in as a parameter.  Note that in DSSSL,
you never deal with an individual node as a data type, only with node
lists.  So if you have a function which seems to deal with a single
node, it is actually dealing with a "singleton node list", or a node
list of only one node.
   The "let" construct here is DSSSL's basic building block for code
locality.  It allows you to define "local" variables whose scope is
just the duration of the block.  In this case, we're defining a
variable called "gr".  The (node-property) function returns the value
of a property of a node (clever, eh? :).  In this case, we're looking
at the "grove-root" property of the node we were passed.  In an SGML
grove, every node has this property, and they all point back to the
node at the root of the grove.  So, it doesn't really matter what you
pass in as an argument to this function, so long as it is in the
current grove.  In fact, we could make this a zero-argument function
and just have it call (current-node) itself, but that would make it a
little less flexible.  So, the (node-property) call returns a node
list of length one.  That is, a node list containing just the node at
the root of the grove.  We assign this value to the variable "gr" so
that we can then build a query expression using it.
   I'll assume that your document contains a <NAME> tag inside of a
<PUBLISHER> tag somewhere in your document.  Here's the "hard way" of
doing it.  There are some easier ways, using some higher level query
functions, but frankly, I can't remember which of the higher level
functions Jade supports at the moment, and this demonstrates the real
structure of the grove, so it just might be more useful in the end.:)

(define (get-publisher-name node)
  (let* ((gr (node-property 'grove-root node))
         (de (node-property 'document-element gr)))
    (let loop ((nl (node-property 'content de)))
      (if (node-list-empty? nl) #f
          (let ((nd (node-list-first nl)))
            (or (and (equal? 'element (node-property 'class-name nd))
                     (if (and (string=? "NAME" (gi nd))
                              (string=? "PUBLISHER"
                                        (gi (node-property 'parent nd))))
                         (data nd)
                         (loop (node-property 'content nd))))
                (loop (node-list-rest nl))))))))

   I am using two higher level functions here, which are the (gi) and
(data) functions, because I know Jade supports them.  The (gi nd)
function is equivalent to (node-property 'gi nd).  The (data nd)
function just returns a string containing the textual contents of the
element.
   I'm using several important DSSSL/Scheme techniques here, namely
let*, named let, and short-circuit (or) and (and) constructs.  If you
have any trouble understanding this, email me privately and I'll
explain.
   Hope this helps (and doesn't confuse you any further).

-Brandon :)


 DSSSList info and archive:  http://www.mulberrytech.com/dsssl/dssslist


Current Thread