Subject: RE: FW: Stopping recursion
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Tue, 22 Nov 2005 11:21:07 -0000
|
There are a few problems with this stylesheet - for example I don't think it
handles a no-namespace schema, or model groups, or types derived by
extension, or perhaps quite a few other things. I'm also not sure whether
the test test=".//@namespace='http://www.w3.org/1999/xlink'" is doing the
right thing: this seems designed to catch element and attribute wildcards,
but I would have thought you also wanted to catch XLink attributes declared
explicitly.
However, to stick to the question you are asking: I think you need to
separate the functionality into two parts: a template that determines
whether an element directly-or-indirectly allows XLink attributes, and a
template that adds an xml:base attribute. The logic should be "if this
element declaration directly-or-indirectly allows XLink attributes, then add
an xml:base attribute", where the logic for testing each element declaration
returns a yes/no result but does not produce a modified element declaration
as output.
This logic will visit the same element many times, which of course has
performance implications. An easy but non-standard answer to that is Saxon
memo functions. A more portable answer is to pass parameters on your
recursive calls indicating the elements already visited: perhaps two lists,
one for those known to allow XLink attributes, another for those known not
to.
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: Mark Seaborne [mailto:mseaborne@xxxxxxxxxxxxxxxxx]
> Sent: 22 November 2005 11:00
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: FW: Stopping recursion
>
> Hi,
>
> I have a 1.0 stylesheet that takes a WXS schema and adds
> xml:base to certain
> complex type definitions. The rule for inclusion of the
> attribute is that
> the complex type must either include directly, or have a descendent in
> another complex type that includes the XLink namespace.
>
> So the stylesheet recurses through each complex type and
> tests to see if
> they contain anything belonging to the XLink namespace. If the type is
> itself a complex type the template is called again to check
> to see if that
> one has any elements within the XLink namespace, and so on.
> If the XLink
> namespace is found then <xsd:attribute ref="xml:base"/> is output.
>
> My problem is that once the XLink namespace is found I would like the
> recursion to stop, mainly because if the namespace is found
> in more than one
> descendent element/attribute declaration the attribute is
> added multiple
> times.
>
> I suspect that either my approach is totally wrong, or this
> is a common
> enough problem that there is a design pattern I can use to achieve the
> effect I want, but I haven't hit on the key words to find it. So any
> pointers would be gratefully received.
>
> This is the template causing the problem:
>
> <xsl:template match="xsd:element" mode="findXLink">
> <xsl:choose>
> <!-- if the element is declared locally (has a type attribute_ -->
> <xsl:when test="@type">
> <!-- remove the namespace prefix from the qname -->
> <xsl:variable name="myType"
> select="substring-after(@type, ':')"/>
> <xsl:for-each
> select="/xsd:schema/xsd:complexType[@name = $myType]">
> <xsl:choose>
> <!-- if the complex type definition includes anything
> in the XLink
> namespace output the xml:base attribute -->
> <xsl:when
> test=".//@namespace='http://www.w3.org/1999/xlink'">
> <xsd:attribute ref="xml:base"/>
> </xsl:when>
> <!-- otherwise apply this template to all of the
> elements declared
> within the complex type -->
> <xsl:otherwise>
> <xsl:apply-templates select=".//xsd:element"
> mode="findXLink"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:for-each>
> </xsl:when>
> <!-- otherwise assume that the element references a
> globally declared
> element, so look for that -->
> <xsl:otherwise>
> <xsl:variable name="myName"
> select="substring-after(@ref, ':')"/>
> <xsl:apply-templates select="//xsd:element[@name = $myName]"
> mode="findXLink"/>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
>
> All the best
>
> Mark
> The information in this e-mail is sent in confidence for the
> addressee only and may be legally privileged. Unauthorised
> recipients must preserve this confidentiality and should
> please advise the sender immediately of the error in
> transmission and then delete this e-mail. If you are not the
> intended recipient, any disclosure, copying, distribution or
> any action taken in reliance on its content is prohibited and
> may be unlawful.
>
> Origo Services Limited accepts no responsibility for any loss
> or damage resulting directly or indirectly from the use of
> this e-mail or the contents. It is your responsibility to
> scan for viruses. Origo Services Limited reserves the right
> to monitor e-mails sent to or from addresses under its
> control. When you reply to this e-mail, you are consenting
> to Origo Services Limited monitoring the content of the
> e-mails you send to or receive from Origo Services Limited.
> If this e-mail is non-business related Origo Services Limited
> is not liable for any opinions expressed by the sender. The
> contents of this e-mail are protected by copyright. All
> rights reserved.
>
>
>
> Origo Services Limited is a company incorporated in Scotland
> (company number 115061) having its registered office at 4th
> floor, Saltire Court, 20 Castle Terrace, Edinburgh EH1 2EN.
|