Re: p:wrap's group-adjacent

Wonderful!  Thank you for the example.

Consider this XML.

<BookStore>
    <Book>
        <Title>My Life and Times</Title>
        <Author>Paul McCartney</Author>
    </Book>
    <Book>
        <Title>Illusions The Adventures of a Reluctant Messiah</Title>
        <Author>Richard Bach</Author>
    </Book>
    <Invoice>
        <Cost>$5</Cost>
    </Invoice>
</BookStore>

Suppose I wanted to wrap the two <Book> elements with a <Books> element, so
it would look like this:

<BookStore>
  <Books>
    <Book>...
    <Book>...
  </Books>
  <Invoice>
     <Cost>...
  </Invoice>
</BookStore>

I should have thought one of these would have worked:

<p:wrap wrapper="Books" match="//Book"
group-adjacent="boolean(self::Book)"/>
<p:wrap wrapper="Books" match="//Book" group-adjacent=". instance of
element(Book)"/>

But they return

<BookStore>
  <Books>
    <Book>...
  </Books>      < unwanted
  <Books>       < unwanted
    <Book>...
  </Books>
  <Invoice>
     <Cost>...
  </Invoice>
</BookStore>

I suppose the intervening elements (author, title) are causing the problem?
How do I wrap the <Book> elements together?

TIA,

James Garriss
http://garriss.blogspot.com




From: Jeni Tennison <jeni@jenitennison.com>
Date: Thu, 18 Sep 2008 22:00:29 +0100
To: James Garriss <james@garriss.org>
Cc: XProc Dev <xproc-dev@w3.org>
Subject: Re: p:wrap's group-adjacent
Resent-From: XProc Dev <xproc-dev@w3.org>
Resent-Date: Thu, 18 Sep 2008 21:01:04 +0000


Hi James,

On 18 Sep 2008, at 21:45, James Garriss wrote:
> The p:wrap step has a group-adjacent option.  I understand what
> p:wrap does, and I think I understand what group-adjacent is trying
> to do.  But I can¹t get it to work.
>
> I think I could get it working if someone would be so kind as to
> translate the middle sentence in this paragraph from the WD into
> English:
>
> The group-adjacent option can be used to group adjacent matching
> nodes in a single wrapper element. The specified XPath expression is
> evaluated for each matching node with that node as the XPath context
> node. Whenever two or more adjacent matching nodes have the same
> ³group adjacent² value, they are wrapped together in a single
> wrapper element.


It's just like group-adjacent in xsl:for-each-group in XSLT 2.0 (not
that that necessarily helps at all).

The main time I use it in XSLT 2.0 is when I have some document
content, such as paragraphs and list items, and I want to group them
together so that all the list items get grouped into a list. For
example:

   <p>
   <p>
   <li>
   <li>
   <p>

would become:

   <p>
   <p>
   <ul>
     <li>
     <li>
   </ul>
   <p>

To do this, I use group-adjacent=". instance of element(li)". This is
an XPath (2.0) expression which returns true for <li> elements and
false for everything else. (An XPath 1.0 equivalent would be group-
adjacent="boolean(self::li)".) So the result of the evaluation is:

   <p>  false
   <p>  false
   <li> true
   <li> true
   <p>  false

Then the processor goes through and groups that first bunch of 'false'
elements together, then the 'true' elements together and then the
'false' elements together. So (with p:wrap) you get:

   <wrapper>
     <p>
     <p>
   </wrapper>
   <wrapper>
     <li>
     <li>
   </wrapper>
   <wrapper>
     <p>
   </wrapper>

which you could then go ahead and process in other ways to unwrap the
<p>s and change the name of the wrapper of the <li>s.

That help any?

Jeni
-- 
Jeni Tennison
http://www.jenitennison.com

Received on Friday, 19 September 2008 22:05:00 UTC