Subject: [xsl] how to rearrange nodes based on a dependency graph? From: Gunther Schadow <gunther@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 20 Dec 2001 14:20:21 -0500 |
I'm hung up on a puzzling problem and need your help. I am relatively new to XSL but thanks to the pretty readable specification and some example I was so far able to find my way. Except when I wanted to be really clever, like here.
The purpose of what I'm doing is kind of what you might know as "literal programming." It's writing a document that explains the detail of some formal language utterance, such as a program, or an XML schema or an IDL specification or whatever have you. The document is to be written for readability and may well have a different flow than what's required for the formal language (program or xsd or whatever.) For example, in describing a Pascal program, I might want to discuss an outline of the main program first before I go into the detail of the procedures. Yet in the program text, the procedures need to come before the main program. The point of course is that the text document should be the main focus of development and maintenance, and the program text should be generated from there. That's where XSLT comes in and falls short? (you tell me if it does of if I fall short :-)
Here is an example. This XML instance discusses a mocked up up XML schema for defining some data.
<frag id='1' requires='2'> BEGIN DoSomethingUseful(); END </frag>
<frag id='2'> PROCEDURE DoSomethingUseful BEGIN ... END </frag>
The <frag> tag has an 'id' (ID) attribute with matching 'requires' (IDREFS) attribute.
The XSL templates will go through the document and discard everything, except when encountering a fragment. It will then will hunt down the requires idrefs to find other fragments that should come first. Of course, if a fragment has already been emitted, it shouldn't appear again. And that't really my big problem.
<xsl:template match='frag'> <xsl:for-each select='@requires'> <xsl:apply-templates select="key('fragkey',.)"/> </xsl:for-each>
<xsl:for-each select='*'> <xsl:call-template name='copy-stuff'/> </xsl:for-each> </xsl:template>
<xsl:template name='copy-stuff'> <xsl:copy> <xsl:for-each select='@*|*'> <xsl:call-template name='copy-stuff'/> </xsl:for-each> </xsl:copy> </xsl:template>
This works nicely, except for the fact that fragment number 2 is emitted twice, first as the dependency of fragment 1 and then because it appears as the next fragment in the document. (Similarly this runs amok if there's a circular dependency.)
I tried to use a variable as a check-off list of fragments already emitted, but that's not possible because XSL "variables" are actually constants. When I try to write such a function in LISP without using global variables and side effects, it get's pretty difficult and the only way to survive here is because I can examine return values. In XSL, I cannot examine the output tree, or can I?
Any suggestions are appreciated. Of course I can dumb down this system and instead of requirement links I could use some kind of sequence number or forward linking and sort by that etc. But I feel that the dependency graph is the most appropriate way to represent this and if XSL is a complete functional language it should have some way to deal with that.
regards, -Gunther
-- Gunther Schadow, M.D., Ph.D. gschadow@xxxxxxxxxxxxxxx Medical Information Scientist Regenstrief Institute for Health Care Adjunct Assistant Professor Indiana University School of Medicine tel:1(317)630-7960 http://aurora.regenstrief.org
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] ANN: Saxon 7.0, Michael Kay | Thread | RE: [xsl] how to rearrange nodes ba, Chris Bayes |
Re: [xsl] is ID definition in DTD n, Joerg Heinicke | Date | [xsl] Text flowing around images in, Rodney Boyd |
Month |