Subject: Re: [xsl] trouble re-rendering XHTML using xsl From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Fri, 15 Feb 2002 08:18:23 +0000 |
Hi Bruce, > What I am hoping to achieve is any form element in <HTML ...> tree > that has a corresponding entry in the <RenderingControl> tree will > convert its attributes to the new one (re-rendering essentially), > and any part of the html that doesn't correspond to a > RenderingControl should just be copied 'as is'. OK, to make this kind of alteration, I recommend that you start with an identity template so that the default action when you apply templates to a node is that it gets copied as-is: <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> The only part of the source XML that you want this process to be applied to is the HTML part - the html element underneath the NewPage document element, and its descendants. So in the template that matches the root node, you should specifically say that you want to apply templates to the HTML part of the page: <xsl:template match="/"> <xsl:apply-templates select="NewPage/html" /> </xsl:template> [Your example hinted that there was an xmlns attribute on the html element - if there is, remember that this will change the namespace of the html element and all its descendants, so you'll need to declare that namespace in your stylesheet, with a prefix, and use that prefix whenever you refer to those elements.] If you run this stylesheet, you'll just get a plain copy of the HTML part of the source XML. You want that HTML to be tweaked slightly. Specifically, if there's an input element in the HTML, and its id is the same as the Name of an ElementToBeChanged, then you want to use the value of the ElementToBeChanged's RenderAs child to add a new attribute to the input element. So you need a special template for input elements. Basically, it should create a copy of the input element as it is, with all its attributes, so the basic form is: <xsl:template match="input"> <xsl:copy> <xsl:copy-of select="@*" /> </xsl:copy> </xsl:template> But the other thing it needs to do is look at the RenderingControl part of the page and work out whether there's an ElementToBeChanged that uses its id. Personally, I'd manage this by setting up a key that matches ElementToBeChanged elements based on their Name, as follows: <xsl:key name="changes" match="ElementToBeChanged" use="Name" /> That enables you to do things like: key('changes', 'btnDoSomething') and get back all the ElementToBeChanged elements that apply to the input element whose id is btnDoSomething. Or more generally, you can use: key('changes', @id) to get the ElementToBeChanged elements that apply to the current input element. I'm not sure whether there can be more more than one such ElementToBeChanged, or whether there can be more than one RenderAs under a particular ElementToBeChanged but I'll assume that there can be one or the other, in which case you need to iterate over the RenderAs elements with an xsl:for-each. You're going to need to add attributes to the input element with this xsl:for-each, so it needs to go within the input element that you're creating; I'd put it after the xsl:copy-of where you copy the existing attributes, in case you want to override any of them: <xsl:template match="input"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:for-each select="key('changes', @id)/RenderAs"> ... </xsl:for-each> </xsl:copy> </xsl:template> Then it's a matter of making the relevant change. You showed three possibilities in your example, where the RenderAs element was 'HIDDEN', 'READONLY' or 'NORMAL'. Since these possibilities are mutually exclusive (any one RenderAs can only have one of those values), you need an xsl:choose to decide between them. Based on the code that you gave, this would look like: <xsl:template match="input"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:for-each select="key('changes', @id)/RenderAs"> <xsl:choose> <xsl:when test=". = 'HIDDEN'"> <xsl:attribute name="visibility">hidden</xsl:attribute> </xsl:when> <xsl:when test=". = 'READONLY'"> <xsl:attribute name="read-only">true</xsl:attribute> </xsl:when> <xsl:when test=". = 'NORMAL'"> <xsl:attribute name="visibility">visible</xsl:attribute> <xsl:attribute name="read-only">false</xsl:attribute> </xsl:when> </xsl:choose> </xsl:for-each> </xsl:copy> </xsl:template> If there are several form elements that you want to be treated in this way, just add them to the list of elements held in the match attribute of the above template. Note that if any of them have content, you'll need to add an <xsl:apply-templates /> instruction after the xsl:for-each in the above, so that their content is copied using the identity template. Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] trouble re-rendering XHTML us, Bruce Kimpel | Thread | [xsl] Table styling, ajay sinha |
Re: [xsl] trouble merging an XHTML , Jeni Tennison | Date | Re: [xsl] sort | uniq via keys, Joerg Pietschmann |
Month |