Hi Simon,
I'm not sure if the word "flatten" was right. I want it to expand all
of the defines so that everywhere there is a "ref" it is replaced by
whatever is in the "define". I could pre-process the file with XSLT
that does that, but I'd rather skip that step since it could result in
a potentially very large intermediate file.
You would also run into difficulties if you ever tried to flatten a
schema for documents with a recursive structure, e.g.:
<define name="section">
<element name="section">
<oneOrMore>
<ref name="paragraph" />
</oneOrMore>
<zeroOrMore>
<ref name="section" />
</zeroOrMore>
</element>
</define>
but perhaps that won't occur in the kind of XML that you're dealing
with.
From the sounds of it, you want to access the most recent
element/attribute element in the template for the <data> element. To
do that consistently through multiple <ref>s and <define>s, you need
to pass it as a parameter. Something like:
<xsl:key name="defines" match="rng:define" use="@name" />
<xsl:template match="rng:element">
...
<xsl:apply-templates>
<xsl:with-param name="node" select="." />
</xsl:apply-templates>
...
</xsl:template>
<xsl:template match="rng:ref">
<xsl:param name="node" />
<xsl:apply-templates select="key('defines', @name)">
<xsl:with-param name="node" select="$node" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rng:define">
<xsl:param name="node" />
<xsl:apply-templates>
<xsl:with-param name="node" select="$node" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="rng:data">
<xsl:param name="node" />
<xsl:value-of select="$node" />
</xsl:template>
You could pass the <ref> element through to the template for the
<define> element, but you'll start losing track of what the context is
if you go through multiple <ref>s on your way from an <element> to a
<data> element.
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list