This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: How to output partial elements?


Hi Jem,

> I have been bashing my brain for days over this and I need help.
> Here is the (style of) input I have:
>
>   <record n="1" type="normal">
>     <foo> <x>... <y>...</y> ...</x> </foo>
>     <bar> <things> ... </things> </bar>
>   </record>
>   <record n="2" type="normal">
>     <foo> <x>... <y>...</y> ...</x> </foo>
>   </record>
>   <record n="3" type="continuation">
>     <bar> <things> ... </things> </bar>
>   </record>
>   <record n="4" type="normal">
>     <foo> <x>... <y>...</y> ...</x> </foo>
>     <bar> <things> ... </things> </bar>
>   </record>
>
> The problem is <record>s 2 and 3: they need to be concatenated.

This isn't *too* hard (wait 'til you get on to the really tricky
grouping problems ;), "just" requires you to think in a declarative
way rather than a procedural way. You want to treat records with a
type of 'continuation' in a different way from those with a type of
'normal', so you need separate templates for the two types:

<xsl:template match="record[@type = 'normal']">
  ...
</xsl:template>

<xsl:template match="record[@type = 'continuation']">
  ...
</xsl:template>

When you come across a record with a type of 'normal', you want to
create a record element and copy the content of that record into it.
You also want to include the content of the next sibling record, if
it's of type 'continuation':

<xsl:template match="record[@type = 'normal']">
  <record>
    <xsl:copy-of select="*" />
    <xsl:copy-of select="following-sibling::record[1]
                           [@type = 'continuation']/*"/>
  </record>
</xsl:template>

On the other hand, if the record is of type 'continuation' then you
don't want to generate a record, and you don't have to worry about the
content of the record because it's already been taken care of by the
previous record. So you do nothing:

<xsl:template match="record[@type = 'continuation']" />

Personally, in this situation, I'd only apply templates to the records
whose type is 'normal' in the first place, so I'd have something like:

<xsl:template match="records">
  <xsl:apply-templates select="record[@type = 'normal']" />
</xsl:template>

<!-- this template will only be applied to records with a type of
     'normal' -->
<xsl:template match="record">
  <record>
    <xsl:copy-of select="*" />
    <xsl:copy-of select="following-sibling::record[1]
                           [@type = 'continuation']/*"/>
  </record>
</xsl:template>

Note that this method only works if there's only one continuation for
each normal record. If there might be more, then I'd use a key-based
solution where you index each continuation record by its closest
normal record and use that to identify which extra fields need to be
added to the new record. If you need help with that, let us know.

Cheers,

Jeni

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


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]