Altova Mailing List Archives

Re: [xsl] repeat and replace loop ( at the same time )

From: Jeni Tennison <jeni@---------------->
Date: 4/2/2002 5:37:00 AM
Hi PG,

> I need to repeat an XML record and replace it at the same time with
> different data.

In your example, the driver for the number of times that you want to
"repeat" the record is 'replace_data.xml'. Since you're working with
two documents, I recommend that you create global variables to hold
the relevant nodes of each -- the record elements:

<xsl:variable name="template" select="/root/record" />
<xsl:variable name="data"
              select="document('replace_data.xml')/root/record" />

You should then apply templates to the record elements from
'replace_data.xml', as you are doing:

<xsl:template match="/">
    <xsl:apply-templates select="$data" />

The template for the record needs to basically copy the template
record, but using the information from the current record. The
template needs to match record elements and create a record element:

<xsl:template match="record">

For the content of the record, you need to process the content of the
template record element, but in doing so, the processor needs to be
aware of the data from the current record. You could store it in a
variable, and then iterate over the content of the template, with
something like:

<xsl:template match="record">
    <xsl:variable name="record" select="." />
    <xsl:for-each select="$template/namedcell">

Or you could apply templates to the content of the template, passing
the record as a parameter, with something like:

<xsl:template match="record">
    <xsl:apply-templates select="$template/*">
      <xsl:with-param name="record" />

<xsl:template match="data" />

<xsl:template match="namedcell">
  <xsl:param name="record" />

Either way, you then need to copy the current namedcell element:

  <xsl:copy-of select="." />

And then you need to identify the relevant child element of the record
element, named by current namedcell element. You can find this by
getting all the child elements of the record and then filtering that
node set to retrieve only those whose name is the same as the name
attribute of the current node, with:

  $record/*[name() = current()/@name]

Assuming that you want to copy the existing data element if there is
no such element, you could use something like:

  <xsl:variable name="value"
                select="$record/*[name() = current()/@name]" />
    <xsl:when test="$value">
      <data><xsl:value-of select="$value" /></data>
      <xsl:copy-of select="following-sibling::data[1]" />

How you actually handle the content of the template is up to you, of
course. The principal of working with separate template and data is:

  - process the data to provide the repetition
  - process the template to provide the structure
  - process the data to provide the values

Getting from the data to the template to the data again means keeping
track of where you are, which you can do with variables or parameters.



Jeni Tennison

 XSL-List info and archive:


These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.