Subject: Re: Move elements to preceding parent
From: Israel Viente <israel.viente@xxxxxxxxx>
Date: Thu, 18 Jun 2009 11:29:43 +0300
|
Dear Ken,
I am sorry it looked as if I ignored your solution. I really tried to
understand it but it had too many new things for me , and it looked
hard to grasp the idea behind it.
I should have write back, but I didn't know where to start from, while
I got another solution that looked more close to my starting point.
I now learnt the lesson and hope you get my sincere apology.
I will read more about xsl:for-each-group, and your explanations on
the code and learn how to use it for my needs.
I must say I am very pleased that you wrote the stylesheet
"defensively anticipating other conditions". You actually anticipated
my needs even before I realised them thoroughly.
Thanks again,
Israel Viente
On Wed, Jun 17, 2009 at 11:37 PM, G. Ken
Holman<gkholman@xxxxxxxxxxxxxxxxxxxx> wrote:
> At 2009-06-17 23:11 +0300, Israel Viente wrote:
>>
>> I really appreciate your code and comments, but after reading it many
>> times, I can't reach to the bottom of the logic here.
>> I'm a newbie so forgive my stupid questions.
>
> As I tell my students, questions are not stupid if they are asked
sincerely.
> I far more appreciate the asking of questions than the ignoring of working
> code that was supplied as requested.
>
>> 1. Why do we need the outer most copy element:
>> > <xsl:template match="body">
>> > <xsl:copy>
>
> In order to preserve the body element when it comes time to group the
> paragraphs.
>
>> How does it work in combination with xsl:for-each-group?
>
> By being the parent of the elements being grouped, matching on <body> gives
> the stylesheet the opportunity to act on all of the children of body. The
> paragraphs you want to massage are children of the body, so the time to act
> on those children is at the time the body arrives at the stylesheet. Since
> we want the body element to be part of the result, we preserve it with
> <xsl:copy>.
>
>> 2. Can you please explain the group-ending-with selection?
>
> You can see by the select="*" that I have selected *all* of the children of
> the body. I want to act on those groups of adjacent <p> elements. But
> since there are other non-<p> elements that could be in the data (there
> aren't any in your data, but how often is a web page made solely of
> paragraphs?) I would be pulling those into the selection as well. After
> all, I want all of the children of body to be processed in child order, I
> only want to engage the special handling when I'm dealing with those
> children that are paragraphs.
>
> Yes your data sample only contained paragraphs, but I try to write my
> stylesheets defensively anticipating other conditions.
>
>> Why do we need *[not(self::p)] ? Doesn't it mean all except p elements?
>
> Indeed it does mean all except <p> elements. By putting non-<p> elements
in
> their own group, they won't interfere with the groups that are comprised of
> <p> elements.
>
> So, adding more narrative to the stylesheet:
>
>> <xsl:template match="body">
>> <xsl:copy>
>> <xsl:copy-of select="@*"/>
>
> The above preserves the body element and any attributes that might be
> attached to it.
>
>> <xsl:for-each-group select="*"
>
> The above selects all of the children of the body.
>
>> group-ending-with="*[not(self::p)] |
>> p[span/@class='chapter'] |
>> p[matches(span[last()],
>> '[.?"]$')]">
>
> The above creates a group for every non-paragraph, a group for every
> chapter, and a group for every consecutive sequence of paragraphs and ends
> that group with a paragraph with the desired punctuation.
>
>> <!--now the information is grouped by p elements that end as
>> required-->
>> <xsl:choose>
>> <xsl:when test="current-group()[last()]
>> [self::p][matches(span[last()],'[.?"]$')]">
>
> The above tells me when I have encountered a group of <p> elements that
ends
> with a paragraph with the desired punctuation.
>
>> <!--in a group of p elements that end as required-->
>> <xsl:copy>
>> <xsl:copy-of select="@*"/>
>
> The above preserves the *first* of those paragraphs, and its attributes.
>
>> <!--preserve the content of the first of these p elements-->
>> <xsl:apply-templates/>
>
> The above preserves the content of that paragraph.
>
>> <!--preserve only the span elements and indentation from the
>> rest;
>> (the indentation is needed because this is paragraph
>> white-space)-->
>> <xsl:apply-templates select="current-group()[position()>1]/
>> (text()[not(normalize-space())] |
>> span)"/>
>
> The above preserves only the content of the other paragraphs in the group.
> If there are no other paragraphs in the group, nothing else is added. If
> there are 15 other paragraphs in the group, all of the content of all of
> them are added. This is the generalized nature of the result: I'm not
> assuming that there is only one other paragraph.
>
>> </xsl:copy>
>> </xsl:when>
>> <xsl:otherwise>
>> <!--in another kind of group so just copy these using identity-->
>> <xsl:apply-templates select="current-group()"/>
>
> The above preserves all of the children of <body> that are not paragraphs
or
> are chapter paragraphs.
>
>> </xsl:otherwise>
>> </xsl:choose>
>> </xsl:for-each-group>
>> </xsl:copy>
>> </xsl:template>
>
> I hope this has helped. Working directly with the sibling axes is fraught
> with problems because of the reach of these axes usually past where we want
> to stop looking. By looking *down* on the data, rather than left and
right,
> one can see a different perspective of your requirement. You expressed
your
> requirement by looking left and right from the given paragraph. I
expressed
> your requirement by looking down at the paragraphs from the <body> parent.
>
> Good luck in your work with XML and XSLT! As you learn more I'm sure
you'll
> love it more.
>
> . . . . . . . . . . . . Ken
>
> --
> Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
> 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
> Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc
> Legal business disclaimers: http://www.CraneSoftwrights.com/legal
|