Re: [xsl] small grouping task

Subject: Re: [xsl] small grouping task
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 26 Feb 2009 21:41:35 -0500
At 2009-02-26 12:57 -0800, Fred Christian wrote:
And actually,
While in the list, there will be only one <br/> per list item, the closing one.
List items are always defined by a <input>....<br/> pair.

That helps.


There will not be extra <br/>'s while in the list.
There will not be anything but whitespace between list items.

So noted.


I didn't realize the value of making these statement until now, or the validity of them. Thanks for the questions.

The stylesheet writer has a responsibility to think of border cases.


Also, there will _not_ be two lists in a <p class="problem">.........</p>

Okay, I'll assume that and not try to handle that situation being present.


I think my source and output are good examples of what has to work now. With sufficient tags to prove the requirements.

Then the example below reproduces what you are asking for, modulo white-space.


If you got my example "desired output" from my example "Note my new source a few more tags", that would fullfill the requirements.
Extra whitespace is ok.

How about less white-space? :{)} I think some gets eliminated by my algorithm, and then some gets introduced by indentation of the result.


> What if you had:
>    <input> test1 <br/> test2
>    <input> test3 <br/>
>
> ... what happens to test2?

Safe to assume that would not happen.
While "in the list" there will not be anything between a <br/> and a <input>.

So assumed.


Am I getting closer?

Your call ... you certainly didn't make it easy. The subject "small grouping task" belies the complexity you've introduced with the content outside of the list items.


Perhaps someone can come up with something more elegant than what is below. I was able to re-use a technique I've used elsewhere of grouping adjacent based on a boolean value, which helped. I can't help but think there might be an easier way, but with the limited time I have, this is all I could come up with quickly.

I hope this helps.

. . . . . . . . . . . . Ken

T:\ftemp>type fred2.xml
<r>
   <p>text</p>
   <randomtag>surronding xhtml</randomtag>
<p class="problem">some <b>xhtml</b> with<br/> no inputs<br/>
  <input type="radio" /> <span class="p">a</span><b>d </b><br />
  <input type="radio" /> <b>g </b><span class="p">b</span><br />
   <p>more</p> generic <b>xhtml</b> with<br/> no inputs<img src="l"/>
</p>
<b>a</b>surronding xhtml<b>b</b>
</r>
T:\ftemp>call xslt2 fred2.xml fred2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<r>
   <p>text</p>
   <randomtag>surronding xhtml</randomtag>
   <p class="problem">some <b>xhtml</b> with<br/> no inputs<br/>
      <ul class="m">
         <li>
            <span class="p">a</span>
            <b>d </b>
         </li>
         <li>
            <b>g </b>
            <span class="p">b</span>
         </li>
      </ul>
      <p>more</p> generic <b>xhtml</b> with<br/> no inputs<img src="l"/>
   </p>
   <b>a</b>surronding xhtml<b>b</b>
</r>
T:\ftemp>type fred2.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="p[@class = 'problem' and input]">
  <p class="problem">
    <!--start the list-->
    <xsl:variable name="foundgroups" as="element(tempgroup)*">
      <!--
The following finds groups that are organized as follows, with the exception
that there may be groups comprised entirely of whitespace between the
groups that look like this:

====
|
|          = copy this
| br
====
====
|
|          = copy this
| br
====
====
|
|          = copy this
|
====
====
| input
|          = make a list item
| br
====
====
| input
|          = make a list item
| br
====
====
|
|          = copy this
| br
====
====
|
|          = copy this
| br
====
====
|
|          = copy this
|
====

-->
      <xsl:for-each-group select="node()" group-starting-with="input">
        <xsl:for-each-group select="current-group()" group-ending-with="br">
          <tempgroup>
            <xsl:apply-templates select="current-group()"/>
          </tempgroup>
        </xsl:for-each-group>
      </xsl:for-each-group>
    </xsl:variable>
    <!--now create up to three groups of groups using only those groups that
        have nodes or non-white-space text, based on whether or not there is
        an input element; if there is, the members of the group of groups
        are the members of the list; if there is not, the members of the
        group of groups are outside the list and simply copied-->
    <xsl:for-each-group select="$foundgroups[* or comment() or
                                             processing-instruction() |
                                             text()[normalize-space() ] ]"
                        group-adjacent="boolean(input)">
      <xsl:choose>
        <xsl:when test="input">
          <!--found the group of list items-->
          <ul class="m">
            <xsl:for-each select="current-group()">
              <li>
                <xsl:apply-templates select="node() except (input | br)"/>
              </li>
            </xsl:for-each>
          </ul>
        </xsl:when>
        <xsl:otherwise>
          <!--found a group that is either before or after the list items-->
          <xsl:apply-templates select="current-group()/node()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </p>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>rem Done!


-- XQuery/XSLT training in Prague, CZ 2009-03 http://www.xmlprague.cz Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18 Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18 G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc Legal business disclaimers: http://www.CraneSoftwrights.com/legal

Current Thread