XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (714 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
4.31Mb size Format: txt, pdf, ePub

As we will see, this

causes the other two cells to be added to the table row.

So let's look at the template rule for the

element. There are two cases to consider here: if the

immediately follows an

element, then it will appear in the same table row as the

element, but in all other cases, it will appear in a new row of its own, preceded by three empty table cells. I would probably have chosen to handle these two cases in two separate template rules, distinguishing the first case using a match pattern such as
match=“rhs[preceding-sibling::*[1][self::lhs]]”
, but the writer of this stylesheet chose to handle both cases in a single rule, like this:




  

    

      

        

          

            diff-

            

          

        

        

      

      

        select=“following-sibling::*[1][name()=‘com’ or

                                        name()=‘constraint’ or

                                        name()=‘vc’ or

                                        name()=‘wfc’]”/>

    

    

      

        

        

          

            

              diff-

              

            

          

          

        

        

          select=“following-sibling::*[1][name()=‘com’ or

                                          name()=‘constraint’ or

                                          name()=‘vc’ or

                                          name()=‘wfc’]”/>

      

    

  


Once again, the code is cluttered by the

instructions that generate change highlighting when required. It also contains a lot of repetition between the two branches of the

.

What the code does is this:

  • If the

    is to appear on the same row as the

    , it outputs a table cell (

    element), colored to reflect any change markings necessary, whose contents are produced by calling

    to process the children of the

    element. It then calls

    to process the following sibling

    ,

    ,

    , or

    element if there is one.
  • If the

    is to appear on a new row, it creates a new table row (

    element), and within this row it first outputs three blank table cells (

    elements). It then outputs a table cell representing the

    element itself and calls

    to process the following sibling element, as in the previous case.

Some people prefer to avoid empty table cells by writing
 
, but that's really necessary only if the table has borders or a background color.

Finally, the last column contains the representation of a

,

,

, or

element if there is one. The rules for these elements are all very similar, and I will show only one of them. The structure is very similar to that for the

element:



  

    

      

        

          

            diff-

            

          

        

        

          

            

              

            

          

          [VC: 

          

          ]

        

      

    

    

      

        

        

          

            

              diff-

              

            

          

          

            

              

                

              

            

            [VC: 

            

            ]

          

        

      

    

  


After studying the previous rule, the basic structure should be familiar. But there is some extra code included in this rule, because the

element is represented as a hyperlink to the description of a validity constraint held outside the table itself. The link is represented in the XML by a
def
attribute, and this is used directly to construct the HTML internal hyperlink. The displayed text of the link is formed by retrieving the element whose
ID
is equal to this
def
attribute, and displaying its text.

So much for formatting the production rules! This is by far the most complicated part of this stylesheet; the rest should be plain sailing. But before we move on, we should ask whether all this logic could have been written in a more straightforward way in XSLT 2.0.

I see this problem as an example of a positional grouping problem. Grouping problems are all concerned with turning a one-dimensional sequence of elements into a hierarchy, and the problem of arranging data in a table can often be understood as a grouping problem in which the hierarchic levels are the table, the rows, and the individual cells.

All grouping problems can be solved by answering two questions:

  • How do you identify an element that can be used to represent the group as a whole (usually the first element of the group)?
  • How do you then identify the remaining members of the same group?

We already have answers to these questions in the existing stylesheet: the group is a row of the table, and we have an XPath expression that selects elements that will be the first in a new row. The other elements in the row are then the following siblings, up to the next element that's a “new row” element.

So here is my XSLT 2.0 solution to this problem. First, in the two template rules for
match=“prod”
and
match=“prodgroup/prod”
, we'll replace the complicated

instruction with a simple call on the named template
show.prod
, with no parameters. This template looks like this:

Other books

Each Shining Hour by Jeff High
Gloryland by Shelton Johnson
When Lightning Strikes by Cynthia Lucas
A Killing Kindness by Reginald Hill
A Rage to Kill by Ann Rule
Weapon of Fear by Chris A. Jackson, Anne L. McMillen-Jackson
Don't Look Back by Amanda Quick
Thinblade by David Wells