Subject: RE: xslt assistance please From: "Evan Lenz" <elenz@xxxxxxxxxxx> Date: Fri, 13 Oct 2000 16:53:32 -0700 |
I wholeheartedly agree with the advice for you to buy Michael Kay's book. I got it cheap and fast from Buy.com. You may wish to check for it there (something like $19, if I remember correctly). What you posted looked like an interesting problem to me, so I took some time out to figure out a solution. In the process, I thought I'd might learn a little about XML Schemas, which is what your example appears to be at least a dialect of. Instead of delving into the actual rules of XSDL, I induced some implicit rules based on your examples and implemented them in the stylesheet. I did this so the stylesheet might apply in more general cases, rather than just this specific example. I'm sure that the schema rules I induced are not complete or entirely correct, so don't rely on this stylesheet to work for every case. In particular, ask yourself if a new example uses something that's not in the example you provided here. If that's the case, the stylesheet would have to be modified to include what is currently unaccounted for. This stylesheet uses the node-set() function, which converts a result tree fragment ($rtf) into a node-set containing one root node, enabling you to access children of that root, etc., with XPath expressions. I needed to do so here in order to pass the "derivatives" tree as a parameter from template to template, using it to determine how given "element" elements should be copied to the result. This function is an extension function provided by Saxon. To make this stylesheet work with other processors besides Saxon, simply change the extension's namespace declaration accordingly, as other processors including XT and Xalan also supply node-set() functions. This may seem overwhelming, as the problem you provided is not necessarily a trivial one. I started simple a few months ago and have since begun to explore and appreciate some of the real power of XSLT. If you have any specific questions about how this stylesheet works, feel free to email me privately. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" exclude-result-prefixes="saxon"> <xsl:template match="/*"> <xsl:copy> <xsl:apply-templates select="*"/> </xsl:copy> </xsl:template> <xsl:template match="*"> <xsl:variable name="derived" select="boolean(@base)"/> <complexType name="{name()}"> <xsl:if test="$derived"> <xsl:copy-of select="@base"/> <xsl:attribute name="derivedBy">restriction</xsl:attribute> </xsl:if> <all> <xsl:if test="$derived"> <xsl:variable name="rtf"> <xsl:copy-of select="*[not(self::element)]"/> </xsl:variable> <xsl:apply-templates select="//*[name() = current()/@base] [1]/element" mode="derived"> <xsl:with-param name="derivatives" select="saxon:node-set($rtf)"/> </xsl:apply-templates> </xsl:if> <xsl:apply-templates select="element"/> </all> </complexType> </xsl:template> <xsl:template match="element"> <xsl:copy-of select="."/> </xsl:template> <xsl:template match="element" mode="derived"> <xsl:param name="derivatives"/> <xsl:variable name="elementName" select="@name"/> <xsl:copy> <xsl:apply-templates select="@*"> <xsl:with-param name="derivatives" select="$derivatives"/> </xsl:apply-templates> <xsl:if test="not(@maxOccurs) and $derivatives/prohibited/* [name() = $elementName]"> <xsl:attribute name="maxOccurs">0</xsl:attribute> </xsl:if> <xsl:variable name="default" select="$derivatives/defaults/* [name() = $elementName][1]"/> <xsl:if test="$default"> <xsl:attribute name="use">default</xsl:attribute> <xsl:attribute name="value"> <xsl:value-of select="$default/@value"/> </xsl:attribute> </xsl:if> </xsl:copy> </xsl:template> <xsl:template match="@*"> <xsl:copy-of select="."/> </xsl:template> <xsl:template match="@minOccurs"> <xsl:param name="derivatives"/> <xsl:variable name="elementName" select="../@name"/> <xsl:choose> <xsl:when test="$derivatives/mandatory/* [name() = $elementName] or $derivatives/mandatory/@fields='ALL'"> <xsl:attribute name="{name()}">1</xsl:attribute> </xsl:when> <xsl:when test="$derivatives/prohibited/* [name() = $elementName]"> <xsl:attribute name="{name()}">0</xsl:attribute> </xsl:when> <xsl:when test="$derivatives/defaults/* [name() = $elementName]"/> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="@maxOccurs"> <xsl:param name="derivatives"/> <xsl:variable name="elementName" select="name(..)"/> <xsl:choose> <xsl:when test="$derivatives/prohibited/* [name() = $elementName]"> <xsl:attribute name="{name()}">0</xsl:attribute> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Have fun learning XSLT! Evan Lenz elenz@xxxxxxxxxxx http://www.xyzfind.com XYZFind, the search engine *designed* for XML Download our free beta software: http://www.xyzfind.com/beta -----Original Message----- From: owner-xsl-list@xxxxxxxxxxxxxxxx [mailto:owner-xsl-list@xxxxxxxxxxxxxxxx]On Behalf Of Azariah Jeyakumar Sent: Friday, October 13, 2000 11:24 AM To: 'XSL-List@xxxxxxxxxxxxxxxx' Subject: xslt assistance please Hi, Would someone help me get started with XSLT? I need to transform 1.xml to 2.xml. Thanks a lot Azariah 1.xml -------- <root> <AccountBaseDescriptorType> <element name="Name" type="string" minOccurs="0" /> <element name="Medium" type="string" minOccurs="0" /> <element name="Address" type="string" minOccurs="0" /> <element name="Id" type="Integer64" minOccurs="0" /> <element name="remaining" type="string" minOccurs="0" /> </AccountBaseDescriptorType> <AccountCreatableDescriptorType base="AccountBaseDescriptorType" > <mandatory> <Name/> <Address/> </mandatory> <prohibited> <Id/> </prohibited> <defaults> <Medium value="TW_MEDIUM_SMTP_HTTP"/> </defaults> </AccountCreatableDescriptorType> <AccountDescriptorType base="AccountBaseDescriptorType" > <mandatory fields="ALL"> </mandatory> </AccountDescriptorType> </root> 2.xml -------- <complexType name="AccountBaseDescriptorType"> <all> <element name="Name" type="string" minOccurs=0 /> <element name="Medium" type="string" minOccurs=0 /> <element name="Address" type="string" minOccurs=0 /> <element name="Id" type="Integer64" minOccurs=0 /> <element name="remaining" type="string" minOccurs=0 /> </all> </complexType> <complexType name="AccountCreatableDescriptorType" base="AccountBaseDescriptorType" derivedBy="restriction" > <all> <element name="Name" type="string" minOccurs=1 /> <element name="Medium" type="string" use="default" value="TW_MEDIUM_SMTP_HTTP" /> <element name="Address" type="string" minOccurs=1 /> <element name="Id" type="Integer64" minOccurs=0 maxOccurs=0 /> <element name="remaining" type="string" minOccurs=0 /> </all> </complexType> <complexType name="AccountDescriptorType" base="AccountBaseDescriptorType" derivedBy="restriction" > <all> <element name="Name" type="string" minOccurs=1 /> <element name="Medium" type="string" minOccurs=1 /> <element name="Address" type="string" minOccurs=1 /> <element name="Id" type="Integer64" minOccurs=1 /> <element name="remaining" type="string" minOccurs=1 /> </all> </complexType> PS1: My goal is to generate 2.xml. So, it is OK to restructure 1.xml to make the transformation easier-to-write. PS2: Performance is not a consideration for the transformation. PS3: The element names "Account...DescriptorType" should not be hard-coded in the .xsl file. XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: xslt assistance please, Lee Goddard | Thread | RE: xslt assistance please, Eliot, Topher |
RE: The document() function....agai, sara . mitchell | Date | RE: The document() function....agai, Andrew Kimball |
Month |