node lists

Subject: node lists
From: "Joerg F. Wittenberger" <Joerg.Wittenberger@xxxxxxxxx>
Date: Tue, 2 Mar 1999 11:29:53 +0100
Hello folks,

I'm rather new to DSSSL (but have some scheme and sgml experience).  I
ran into several problems and finaly think that I might have
missunderstood the philisophy behind.  Let me explain my problem and
let's see whether this trigger some better solution.

I work with jade, docbook and the modular style sheets.

Our application is based on docbook but requires some extensions.
Those are (in the majority) elements on section level, which shall
be required and uniformly named.  Here a short example:

<!element hld - - (intro, extinterface, dataobjects) >
<!element extinterface - o (dataobjects, userinterface, commands,
messages, files)>

All of them have an internal structure like "section" from docbook,
except that they don't have a title etc. (this shall be generated from
the style sheets).  Actually a document like:

<hld>
<intro>
<para>bla bla</para>
<extinterface>
<dataobjects>
<para>blub</para>

Should be processed like this docbook equivalent:
<book>
<chapter><title>hld</title>
<section id="hld.intro"><title>Introduction</title>
<para>bla bla.</para>
</section>
<section id="hld.extinterfaces>><title>External Interfaces</title>
<section id="hld.extinterfaces.dataobjects>
 <title>Dataobjects</title>
<para>blub</para>
</section>
</section>
</chapter>
</book>

The problem is, that those section are hard to enumerate.  (Even worse
we have an attibute, which supresses the section from the output -
hence it is not supposed to be counted.  But that's a minor problem.)

Additionaly things like extinterfaces should be subdoc's if possible
at all.

The only solution I found until now, which allows me to enumerate the
section properly looks like the following.  I'm not satisfied with it,
because I want to use as much as possible from the docbook style
sheets, but I am using too few.  At least the cross referencing and
the generated html navigation elements are something I definatly don't
want to loose.  But even that and the diversion into the html files
dosn't work.

If I had something like (make-node children-node-list), which would
create a fresh node list with the specified children, which in turn I
could process as if I had read it from a file, that would be most of
the deal.  I could say:

(element intro
 (process-node-list (make-node gi: section
                      (node-list 
                       (make-node gi: title "Introduction")
                       (children (current-node))))))
                      
And I was done.  But I could not find such a function yet.

Let's go for what I did, maybe someone can help.

The heard of the processing is this function:

; Process some nodes according to alist, which is a list of pairs
; ( normalized-string . (lambda (alist snl nl)) )
; If the gi of the current first node in nl matches transfer parsing
; to this procedure.  Snl is the current node and nl the unparsed
; rest.  Otherwise process the first node of nl and continue.
; reuse global mode for defaulted elements

(define (process-assoc-node-list alist nl)
  (if (node-list-empty? nl)
      (empty-sosofo)
      (let* ((this-node (node-list-first nl))
	     (this-gi (gi this-node))
	     (is-special (assoc this-gi alist)))
	(if is-special
	    ((cdr is-special) alist this-node (node-list-rest nl))
	    (make sequence
		  (process-node-list this-node)
		  (process-assoc-node-list alist (node-list-rest nl)))))))

; A list of gi's to act upon.
; ( (gi title-text optional-substructre)* )
; The optional-substructure is recursive the same.

(define my--hld-sections
  `(( "Introduction"             "Überblick"              )
    ( "Task"                     "Aufgabe"                )
    ( "DataFlow"                 "Datenfluß"              )
    ( "DataObjects"              "Datenobjekte"           )
    ( "TestStrategy"             "Teststrategie"          )
    ( "PerformanceConsideration" "Performenzbetrachtung"  )
    ( "ExternalInterfaces"
      "Externe Schnittstellen"
      ("Dataobjects"    "Datenobjekte (extern)")
      ("UserInterfaces" "Bildschirmmasken")
      ("Commands"       "Kommandos")
      ("Messages"       "Nachrichten")
      ("Files"          "Dateien")
      )
    ( "Dependencies"             "Dependencies"           )))

; number: hirarichical section number (reversed)
; seq: list of pairs (tag-name . heading)
;      determines the sequence of sections to expect
;      *must* math with DTD!

(define (my--hld-section-trigger number seq)
  (cons (normalize (if (null? seq) "" (caar seq)))
	(my--hld-section number seq)))

Here we have the attribute "status" which might have the value
"omitted", if it has the whole section is left out. If it has the
value "todo", we know the author is not finished yet and mark it in
the output as incomplete ("Unvollständig: ").  This complicates the
whole thing a bit more, but I don't want to remove it - I might break
the code...

(define (my--hld-section number seq)
  (lambda (alist me rest)
    (let* ((status (attribute-string (normalize "status") me))
	   (next (cdr seq)))
      (if (equal?  (normalize "omitted") status) ; skip it
	  (process-assoc-node-list
	   (cons (my--hld-section-trigger number (cdr seq)) alist)
	   rest)
	  (let* ((f-num (format-number-list (reverse number) "1" "."))
		 (word (cadar seq))	; The Heading of this section
		 (text (cond		; marked for things TODO
			((equal?  (normalize "todo") status)
			 (literal f-num " Unvollständig: " word))
			(else
			 (literal f-num " " word)))))
	    (make sequence
		  (my--title (length number) #f text)
		  ; find substructures, subdocs etc.
		  (process-assoc-node-list
		   `(( ,(normalize "Section")
		       . ,(my--hld-inner-section (cons 1 number)))
		     ,@(let ((inner (cdr (cdar seq)))) ; substructre
			 ; FIXME: This should be cleaner with an extra
			 ; definition creating the parser here and
			 ; in hld, at the first place
			 (if (not (null? inner))
			     `(( ,(normalize (caar inner))
				 . ,(my--hld-section (cons 1 number) inner)))
			     '()))
		     . ,alist)
		   (children me))
		  ; now process following sections at the same level
		  (process-assoc-node-list
		   (cons (my--hld-section-trigger
			   `( ,(+ (car number) 1) . ,(cdr number))
			   (cdr seq))
			 alist)
		   rest)))))))

; "Section" is recursive and might appear inside of others

(define (my--hld-inner-section number)
  (lambda (alist me rest)
    (make sequence
	  (my--title
	   (length number) #f
	   (literal (format-number-list (reverse number) "1" ".") " ")
	   (section-title-sosofo me))
	  ; process subsections of the current one
	  (process-assoc-node-list
	   `(( ,(normalize "Section")
	       . ,(my--hld-inner-section (cons 1 number)))
	     . ,alist)
	   (children me))
	  ; process following sections at the same level
	  (process-assoc-node-list
	   `(( ,(normalize "Section")
	       . ,(my--hld-inner-section
		   `( ,(+ (car number) 1) . ,(cdr number))))
	     . ,alist)
	   rest))))


Thanks for reading, who can help me to find a better solution?
I'd really like not to parse the whole thing.

Reragards
/Jerry


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


Current Thread