Subject: Re: [xsl] Rename attributes and nodes maybe using variables From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 9 Jul 2003 09:55:06 +0100 |
Hi Kai, > In the XML-File are nodes with the name "IMAGE" and the first > attribute should reflect the name and the second attribute the > location of the image. The name of these attribute is not fix, but > in the result the furst attribute should be named "name" and the > second "url" and the old name should be stored in attribute so in > the second transformation these attributes get there old name. This requirement seems to be saying that the names of the attributes aren't known in advance, and you want to use their "position" to determine how to treat their content. In XML, the order of attributes is insignificant -- XML parsers are not required to report attributes in the same order as they encounter them. As far as an XSLT processor is concerned: <IMAGE name="test5" url="/vol/pictures/test5.jpg"/> is exactly the same as: <IMAGE url="/vol/pictures/test5.jpg" name="test5"/> Of course attributes are reported in some kind of order, so you can use @*[1] and @*[2] to get the "first" and "second" attribute if you want, but you have no guarantees from processor to processor (or even from transformation to transformation) about whether @*[1] is going to give you the name attribute or the url attribute. What this boils down to is that if you really need to use the position of an attribute to determine its meaning, then you need to use a non-XML-aware process to do it -- something that treats the XML document as a string of characters. You can't use XSLT. On the other hand, if you can guess at the names that might be used for the attributes, then you can rename them by creating templates that match the old name and create an attribute with the new name. For example, to map the attribute 'label' to an attribute called 'name', use the following template: <xsl:template match="@label"> <xsl:attribute name="name"> <xsl:value-of select="." /> </xsl:attribute> </xsl:template> To also add an 'old_atr_name' attribute with the value of the name of the original attribute, use another <xsl:attribute> instruction to create the attribute: <xsl:template match="@label"> <xsl:attribute name="name"> <xsl:value-of select="." /> </xsl:attribute> <xsl:attribute name="old_atr_name"> <xsl:value-of select="name()" /> </xsl:attribute> </xsl:template> You should be able to put together a similar template to map the 'locaction' attribute to a 'url' attribute. Just add these templates to the templates from yesterday. > In other parts of the File are Nodes with the node-name REGIONSET > and the attribute "image". But in this attribute "image" I need not > the name, but the location where I can find the file. > > So this attribute has to be replaced with the url of the node IMAGE > where the value of the "image" and "name" are the same. (Maybe > saving the url of the images in variables with the name of the image > should be helpful) To do this, you need a key. Index all the <FOTO>, <PHOTO> etc. elements by their name (or equivalent) attribute. For example: <xsl:key name="images" match="FOTO | PHOTO | BILD | BILDCHEN | IMG | IMAGE" use="@name | @label" /> Then to get the URL of the image with a particular name (e.g. 'test1'), you can use the key to retrieve the relevant element, and then step down to its url attribute: key('images', 'test1')/@url So the template for the <REGIONSET> element is: <xsl:template match="REGIONSET"> <REGIONSET image="{key('images', @image)/@url}" oldvalue="{@image}"> <xsl:apply-templates /> </REGIONSET> </xsl:template> Again, just add this template to your stylesheet. > The second stylesheet: > > The second should undo all, the first stylesheet did. So rename ever > changed node and attribute with the original stored name and value > and delete the new created attributes. Again, you need the identity template as the basis for your stylesheet, because mostly you just want to copy the nodes. Then you need a template that matches an <IMAGE> element: <xsl:template match="IMAGE"> ... </xsl:template> You need to work out the names of the new element, its 'name' attribute and its 'url' attribute. You can do this by checking if the 'oldname', 'old_atr_name' and/or 'old_atr_url' attributes are present, and using their values if they are, or the default values ('IMAGE', 'name' and 'url') if they aren't: <xsl:variable name="new_ele"> <xsl:choose> <xsl:when test="@oldname"> <xsl:value-of select="@oldname" /> </xsl:when> <xsl:otherwise>IMAGE</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="new_atr_name"> <xsl:choose> <xsl:when test="@old_atr_name"> <xsl:value-of select="@old_atr_name" /> </xsl:when> <xsl:otherwise>name</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="new_atr_url"> <xsl:choose> <xsl:when test="@old_atr_url"> <xsl:value-of select="@old_atr_url" /> </xsl:when> <xsl:otherwise>url</xsl:otherwise> </xsl:choose> </xsl:variable> To use these names for the new element and attributes, you need to create them with <xsl:element>/<xsl:attribute> instructions and use an attribute value template in the name attribute, pointing to the relevant variable: <xsl:element name="{$new_ele}"> <xsl:attribute name="{$new_atr_name}"> <xsl:value-of select="@name" /> </xsl:attribute> <xsl:attribute name="{$new_atr_url}"> <xsl:value-of select="@url" /> </xsl:attribute> </xsl:element> The template for the <REGIONSET> element is even easier because you just need to make the value of the image attribute the value of the oldvalue attribute: <xsl:template match="REGIONSET"> <REGIONSET image="{@oldvalue}"> <xsl:apply-templates /> </REGIONSET> </xsl: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] Rename attributes and nodes m, Kai Lienemann | Thread | RE: [xsl] Rename attributes and nod, Michael Kay |
RE: [xsl] identity transform - incl, Andrew Welch | Date | [xsl] Paragraph indenting., XSL Chatr |
Month |