First of all, to clarify:
At 2009-09-25 17:44 -0400, Wendell Piez wrote:
Ken's circumlocution reflects what you have to do in XSLT 1.0 to be
namespace-safe.
The discussion regarding XSLT 1 came from an observation I made when
someone posted a solution for an XSLT 2 issue that was not namespace
safe in either XSLT 1 or XSLT 2 but someone reading the list using
XSLT 1 might have thought to use it since the XSLT 2 functions were
not available:
At 2009-09-25 07:50 -0400, I wrote:
For the maillist record, the above approach is not namespace-safe
and so is not a general solution for XSLT 1.0. Rather, the
following would be ...
Now we are back to XSLT 2.0 again and there are better functions in
XSLT 2 than in XSLT 1.
At 2009-09-25 23:08 -0400, ac wrote:
I am surely missing something here as, assuming that $new is a
different node from the current node, that their attributes can vary
and be in different namespaces, and that I need to copy only the
attributes of the current node that are not also in $new, in a
namespace safe way, with XSLT 2,
Fine ... that is a brand new requirement and it has been confusing to
follow the one discussion thread when requirements keep changing.
As David said, intersection and exception works on node identity and
not node name. Think of the infamous Venn diagram and you only get
overlap when you are talking about the same things. This diagram is
very useful in the XPath classroom when teaching these node set facilities.
In the case you are citing above, with attributes in $new and
attributes in the source tree, those are mutually exclusive circles
of a Venn diagram and so do not overlap and so intersection and
exception do not give you what you want.
I do not see how I can do like
<xsl:copy-of select="@*[not(name() = ($new/@*/name()))]"/>
with attribute(), or even in any other way, namespace safe or not.
Only because you have not yet found it in the specification. My
students come to class complaining about things XSLT doesn't do, but
most of the time that is only because they haven't learned it yet,
not because it doesn't do it.
local-name() can be useful but, as we all know, two nodes with the
same local-name and different namespaces, are two different things.
Indeed ... so instead we use different functions that *are* namespace-safe.
The good news are that known literal node names can be handled in a
namespace safe way in XSLT2
The verbose techniques I brought up earlier were for XSLT 1 because
that was the premise I set out in the discussion of not having the
"except" operator available. Now that you are talking about XSLT 2
we don't have to deal with the verbose use of the functions I gave
you in order to be namespace-safe. The following in XSLT 2:
<xsl:copy-of select="@*[not(node-name(.) = $new/@*/node-name(.))]"/>
... will copy the current nodes attributes that do not have the same
namespace-qualified-name as any of the attributes of the elements in
the $new variable.
From my interpretation of your question and your environment, I
think this will do what you want.
This is also why I started dreaming that maybe one day, we could use
something like the curly brackets (or a function like QName()) to
try to get around ...
But then you are talking about namespaces that are quoted in your
stylesheet and not namespaces that are found in other nodes. For
what you are asking for there you can do:
<xsl:copy-of select="@*[not(node-name(.) = QName("urn:X-Crane","x"))]"/>
Examples are below. Remember that creating short examples of what
you need will help you when testing candidate solutions.
I hope this helps.
. . . . . . . . . . . . Ken
p.s. my XSLT/XQuery/XPath hands-on classes are comprehensive and
exhaustive (some say "exhausting") with encyclopaedic coverage of
every element, every attribute, every keyword and every function of
the specifications versions 1.0 and 2.0 ... the next class is coming
up soon on the US east coast ... details on our home page ... in such
a class you do learn everything that features in these specifications
are capable of, not just a focused subset of problem solutions
t:\ftemp>type ac.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/doc">
<results>
<xsl:copy-of select="//namespace::*"/>
<result1>
<xsl:for-each select="P">
<P>
<xsl:copy-of select="@*[not(node-name(.)=$new/@*/node-name(.))]"/>
</P>
</xsl:for-each>
</result1>
<result2>
<xsl:for-each select="P">
<P>
<xsl:copy-of
select="@*[not(node-name(.)=QName('urn:X-Crane','x'))]"/>
</P>
</xsl:for-each>
</result2>
</results>
</xsl:template>
<xsl:variable name="new" as="element()*"
xmlns:c1="urn:X-Crane" xmlns:c2="urn:X-Crane2">
<A c1:x="a-xattr1" c2:z="a-zattr2"/>
</xsl:variable>
</xsl:stylesheet>
t:\ftemp>type ac.xml
<doc xmlns:p="urn:X-Crane" xmlns:q="urn:X-Crane2">
<P p:x="xattr1" q:y="yattr2"/>
<P q:x="xattr2" p:y="yattr1"/>
</doc>
t:\ftemp>xslt2 ac.xml ac.xsl
<?xml version="1.0" encoding="UTF-8"?>
<results xmlns:p="urn:X-Crane" xmlns:q="urn:X-Crane2">
<result1>
<P q:y="yattr2"/>
<P q:x="xattr2" p:y="yattr1"/>
</result1>
<result2>
<P q:y="yattr2"/>
<P q:x="xattr2" p:y="yattr1"/>
</result2>
</results>
t:\ftemp>
--
Upcoming hands-on code list, UBL, XSLT, XQuery and XSL-FO classes.
Interested in other classes? http://www.CraneSoftwrights.com/s/i/
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--