Re: [xsl] Copying Groups of Attributes

Subject: Re: [xsl] Copying Groups of Attributes
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Tue, 13 Feb 2001 09:18:45 +0000
Hi Ciaran,

David Carlisle wrote:
>         But I was more thinking along the lines of
>
>          <xsl:copy-of select="coreattrs"/>
>
>         where coreattrs has been defined elsewhere in the XSL.
>
> <xsl:call-template name="coreattrs"/>
>
> ....
>
> <xsl:template name="coresttrs">
>   <xsl:copy-of select="@id|@class|@this|@that"/>
> </xsl:template>

There are a couple of other ways:

You could use XML entities to give the attribute names.  Define the
entities in the document type declaration for the stylesheet:

<![DOCTYPE xsl:stylesheet [
<!ENTITY coreattrs '@id|@class|@style|@title'>
]>

and then use the entity name within the xsl:copy-of in the main code:

<xsl:template match="p">
   <p>
      <xsl:copy-of select="&coreattrs;" />
   </p>
</xsl:template>

Or you could store the relevant attribute names in a separate XML
structure somewhere, e.g.:

--- definitions.xml ---
<attgroup name="coreattrs">
   <attribute name="id" />
   <attribute name="class" />
   <attribute name="style" />
   <attribute name="title" />
</attgroup>
---

[Note: you can make up your own XML structure for the above - you
might notice that it looks similar to various schema structures, and
want to use a one of the schema vocabularies to represent it.]

With the above structure, you could retrieve the list of coreattrs
through something like:

  document('definitions.xml')//attgroup[@name = 'coreattrs']/attribute

[Note: you could probably do this more efficiently with keys or ids.]

Perhaps store that in a variable:

<xsl:variable name="coreattrs"
              select="document('definitions.xml')//attgroup[@name = 'coreattrs']/attribute" />

And then copy all those attributes whose name is equal to one of the
@names of the attribute elements stored in the $coreattrs variable:

<xsl:template match="p">
   <p>
      <xsl:copy-of select="@*[name() = $coreattrs]" />
   </p>
</xsl:template>

This is quite a nice method because it separates the information that
you want from how you use it.  You can easily go and edit
definitions.xml if the membership of coreattrs changes, without having
to touch the XSLT code.

A final point: xsl:copy-of gives an exact copy of a node, including
its name and value, and obviously it only copies a node if it's there
to be copied, so you don't need the xsl:ifs testing for its presence.
If you are ever changing the name of one of these attributes -
changing lang to xml:lang, for example - then you can't use
xsl:copy-of.  Using a separate named or moded template as David
suggested gives you a lot more flexibility and extensibility than the
suggestions given above, and could be combined with the second
technique above quite elegantly.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread