This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Copying unknown attributes in XML to XML transformation?
Hello,
Jeni Tennison wrote:
>
> David C. wrote:
> > ] Try this, Bill:
> > ]
> > ] <xsl:template match="connectionFactory">
> > ] <xsl:element name="connectionFactory">
> > ] <xsl:for-each select="@*">
> > ] <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute>
> > ] </xsl:for-each>
> > ] <xsl:attribute name="host"><xsl:value-of select="$host"/></xsl:attribute>
> > ] <xsl:attribute name="port"><xsl:value-of select="$port"/></xsl:attribute>
> > ] </xsl:element>
> > ] </xsl:template>
> >
> > That works, but it is equivalent to the rather shorter
> >
> > <xsl:template match="connectionFactory">
> > <connectionFactory host="{$host}" port="{$port}">
> > <xsl:copy-of select="@*"/>
> > </connectionFactory>
> > </xsl:template>
>
> I think it's not quite equivalent, because of the order in which the
> attributes are added. In the first, any existing 'host' or 'port'
> attributes are added within the xsl:for-each, but then overridden by
> the xsl:attribute instructions that add the values from the variables.
> In the second, the 'host' and 'port' attributes are given values from
> the variables, but then overridden by the attributes copied onto the
> element.
Yes, that's exactly what I found (and had tried orginally). Thanks for
clarifying this for everybody.
> I think the first *is* equivalent to:
>
> <connectionFactory>
> <xsl:copy-of select="@*" />
> <xsl:attribute name="host">
> <xsl:value-of select="$host" />
> </xsl:attribute>
> <xsl:attribute name="port">
> <xsl:value-of select="$port" />
> </xsl:attribute>
> </connectionFactory>
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>
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>
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"/>
> Cheers,
>
> Jeni
>
> ---
> Jeni Tennison
> http://www.jenitennison.com/
Thanks Jeni and thanks again for everyone's input.
-Bill Burton
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list