Re: [xsl] Producing 1 style sheet from 1 with many imports from others

Subject: Re: [xsl] Producing 1 style sheet from 1 with many imports from others
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Tue, 2 Apr 2002 10:09:17 +0100
Hi Gary,

> I am wondering if anyone knows of a way to produce a single complete
> style sheet from one that imports from many others (whilst removing
> the templates, variables and parameters that duplicate and are
> overwritten by the processor through higher presedence!).

That's actually quite difficult, in the general case, because of the
way that importing works with templates. Consider the following
situation:

--- main.xsl ---
<xsl:import href="imported.xsl" />

<xsl:template match="foo[@bar = 'baz']">
  ... <xsl:apply-imports /> ...
</xsl:template>
---

--- imported.xsl ---
<xsl:template match="foo[@bar]">
  ...
</xsl:template>
---

The template matching foo elements with bar attributes is overridden
for those foo elements whose bar attribute equals 'baz', but isn't
overridden for other foo elements. The two templates have the same
priority, so it's an error to have them in the same stylesheet, unless
we add a priority to one or the other, but doing that might mess up
other priorities that we have in the stylesheet.

Also, the xsl:apply-imports instruction within the overriding template
specifically applies the templates from the imported stylesheet; you
can't replicate that effect within a single stylesheet without using
modes, so again whatever merged the stylesheets would have to rewrite
the stylesheets quite significantly.

Most stylesheets don't contain anything as complex as this, however,
so you don't have to worry about it too much. Probably the easiest
thing to do is to write a stylesheet that contains template matching
xsl:stylesheet and xsl:import elements, which passes information about
the existing (i.e. overriding) components in a parameter. Something
along the lines of:

<xsl:template match="xsl:import">
  <xsl:param name="overrides" select="/.." />
  <xsl:apply-templates select="document(@href)/xsl:stylesheet">
    <xsl:with-param name="overrides" select="$overrides | ../xsl:*" />
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="xsl:stylesheet">
  <xsl:param name="overrides" select="/.." />
  <xsl:apply-templates select="xsl:import">
    <xsl:with-param name="overrides" select="$overrides" />
  </xsl:apply-templates>
  <xsl:for-each select="*[not(self::xsl:import)]">
    <xsl:if test="not($overrides[local-name() = local-name(current())
                                 and @name = current()/@name])">
      <xsl:copy-of select="." />
    </xsl:if>
  </xsl:for-each>
</xsl:template>

You should also do things like add the version,
extension-element-prefixes and exclude-result-prefixes attributes from
the parent xsl:stylesheet element to the copied components, to
maintain consistency, but hopefully the above gives you some ideas.

Cheers,

Jeni

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


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


Current Thread