[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] RE: Processing Recursive Groups
That's interesting Michael. I never thought of that scenario. But I feel
kind of dumb using the wrong brackets!! (i guess it happens to us all, once
in a while).
I apologize to David for not including more code information. I'm fairly new to the list and I just figured nobody wanted to see the rest of the XSLT, only the problem parts. My XSLT is fairly long so here's some more good stuff. The input file is an XSD. I cannot post the input file as it is against company policy. But viewing my input shouldn't really make a difference since an XSD is highly structured and does not have any room for customization. The script should work with any XSD. I use XalanJ 2.7/XPath 1.0. By the way, I fixed my stupid mistake with the brackets and it worked the way I originally intended (but it doesn't handle what Mike stated). And from my previous thread about generating custom ID's from parent nodes, I was able to find the exact solution using Jeni's code snippet here: http://www.biglist.com/lists/xsl-list/archives/200107/msg01783.html <!-- Declare indexes for different sections of the schema --> <xsl:key name="allTopElements" match="/*/xsd:element" use="concat(@name,' ',@type,' ',@ref)"/> <xsl:key name="allTypes" match="xsd:simpleType[string(@name)] | xsd:complexType[string(@name)]" use="@name"/> <xsl:key name="allGroups" match="xsd:group[string(@name)]" use="@name"/> <xsl:key name="allAttributeGroups" match="xsd:attributeGroup[string(@name)]" use="@name"/> <!-- Begin processing from root --> <xsl:template match="/"> <xsl:element name="Metadata"> <xsl:element name="Elements"> <xsl:for-each select="/*/xsd:element"> <xsl:sort select="@name"/> <xsl:apply-templates select="."/> </xsl:for-each> </xsl:element> </xsl:element> </xsl:template> <!-- Process an element if encounted --> <xsl:template match="xsd:element[string(@name) or string(@ref)]"> <xsl:call-template name="processElement"/> </xsl:template> <!-- Continue processing after encountering sequences and choices --> <xsl:template match="xsd:all | xsd:sequence | xsd:choice"> <xsl:apply-templates select="*"/> </xsl:template> <xsl:template match="node() | @*"/> <!-- Process and format elements --> <xsl:template name="processElement"> <xsl:element name="element"> <xsl:if test="@name"> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> </xsl:if> <xsl:if test="string(@type)"> <xsl:attribute name="type"> <xsl:value-of select="@type"/> </xsl:attribute> </xsl:if> <xsl:if test="string(@ref)"> <xsl:attribute name="ref"> <xsl:value-of select="@ref"/> </xsl:attribute> </xsl:if> <!-- Process anonymous type definitions, if any --> <xsl:for-each select="xsd:simpleType | xsd:complexType"> <xsl:call-template name="processType"/> </xsl:for-each> </xsl:element> </xsl:template> <!-- Process both anonymous and declared type definitions, and handle extensions --> <xsl:template name="processType"> <xsl:variable name="extension" select="*/xsd:extension"/> <xsl:for-each select="$extension"> <xsl:attribute name="type"> <xsl:value-of select="@base"/> </xsl:attribute> <xsl:attribute name="extended">true</xsl:attribute> <xsl:if test="node()"> <xsl:element name="extended"> <xsl:call-template name="processAllChildren"/> </xsl:element> </xsl:if> </xsl:for-each> <xsl:call-template name="processAllChildren"/> </xsl:template> <!-- Process all children under any element, type, or group --> <xsl:template name="processAllChildren"> <xsl:call-template name="processAttributes"/> <xsl:for-each select="xsd:attributeGroup"> <xsl:if test="string(@ref)"> <xsl:for-each select="key('allAttributeGroups',string(@ref))"> <xsl:call-template name="processAttributes"/> </xsl:for-each> </xsl:if> </xsl:for-each> <xsl:for-each select="xsd:group"> <xsl:if test="string(@ref)"> <xsl:choose> <xsl:when test="not(ancestor::xsd:group[@name=current()/@ref])"> <xsl:for-each select="key('allGroups',string(@ref))"> <xsl:apply-templates select="*"/> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:element name="group"> <xsl:attribute name="ref"> <xsl:value-of select="@ref"/> </xsl:attribute> </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:for-each> <xsl:apply-templates select="*"/> </xsl:template> <!-- Process all attributes and parse comments --> <xsl:template name="processAttributes"> <!-- This is some attribute processing which is kind of long but efficient, necessary, and simple --> <xsl:call-template name="processComments"/> </xsl:template> <!-- Parses comments --> <xsl:template name="processComments"> <!-- This section parses comments in the actual <!-- comment tags (not annotation tags). It uses a bunch of string processing. Simple, long, yet efficient --> </xsl:template> Wasiq Shaikh ----Original Message Follows---- Some good news: there are a couple of examples in my book of code that checks for cycles. The bad news is that they have bugs. Testing whether a group refers directly to itself isn't good enough, you need to test for cycles such as A referring to B and B referring to A. You can't do this with a simple check on the ancestor axis, even if you get the brackets right. Basically, when your template calls itself recursively, it has to pass a parameter containing the name of the referencing group; on each recursive call you need to append another name to the list supplied when you were called, and then to check for cycles you need to check that your own name is not anywhere on the list of callers. Michael Kay http://www.saxonica.com/ _________________________________________________________________ Windows Live Hotmail gives you the control you need to help you keep your e-mail private, safe and secure. See for yourself! www.newhotmail.ca?icid=WLHMENCA147
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|