Re: [xsl] Copying unknown attributes in XML to XML transformation?

Subject: Re: [xsl] Copying unknown attributes in XML to XML transformation?
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Sat, 27 Jan 2001 11:30:27 +0000
Hi Bill,

> Yes, it is.  The above is a little more verbose than the original solution
> proposed by a couple of people (below), but I think the syntax is simpler
> and if there are more than two or three attributes that need their values
> substituted, will be easier to maintain than this solution:
>   <xsl:template match="connectionFactory">
>     <connectionFactory host="{$host}" port="{$port}">
>       <xsl:copy-of select="@*[name()!='host' and name()!='port']"/>
>     </connectionFactory>
>   </xsl:template>

Very possibly. One problem with the above solution in the general case
is that it doesn't work well with namespaced attributes: you need to
test local name and namespace URI or use an identity test to get
those, e.g.:

    select="@*[not(local-name() = 'foo' and
                   namespace-uri() = '')]" />


    select="@*[count(.|../@bar:foo) != count(../@bar:foo)]" />

Copying everything and then overriding those attributes that you want
different values for saves you from having to do either of these.
> After a bit of experimentation, I came up with this:
>   <xsl:template match="connectionFactory">
>     <connectionFactory host="{$host}" port="{$port}">
>       <xsl:copy-of select="@*[not(contains('host|port',name()))]"/>
>     </connectionFactory>
>   </xsl:template>

That's great as long as you don't have attribute names that are
substrings of each other.  For example, if you wanted to filter out
'hostPort' attributes, but wanted to keep a 'host' attribute, then the
above solution will filter out the 'host' attributes as well.

> It still seems rather odd to me that where copying a selected list
> attributes (in this case) is so easy with:
>   <xsl:copy-of select="@attr1|@attr2|@attr3"/>
> that there ought to also be a similarly easy way to copy all nodes except
> the specified ones.  Maybe something like:
>   <xsl:copy-of select="@*[exclude(@attr1|@attr2|@attr3)]"/>
> or
>   <xsl:copy-of select="@*" exclude="@attr1|@attr2|@attr3"/>

If we were dealing with elements, then you could do:

  <xsl:copy-of select="*[not(self::el1 or self::el2 or self::el3)]" />

But you can't use the self:: axis with attributes. Maybe just a set
difference function would work, like saxon:difference():

  <xsl:copy-of select="saxon:difference(@*, @host | @port)" />



Jeni Tennison

 XSL-List info and archive:

Current Thread