This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Identifying two tags that share some attribute names and values - XPATH 2.0 SOLUTION
- From: "Evan Lenz" <evan at evanlenz dot net>
- To: <xsl-list at lists dot mulberrytech dot com>
- Date: Mon, 6 May 2002 15:00:14 -0700
- Subject: RE: [xsl] Identifying two tags that share some attribute names and values - XPATH 2.0 SOLUTION
- Reply-to: xsl-list at lists dot mulberrytech dot com
Zack Brown wrote:
> Wow, a very simple solution!
There's actually another way you can do this that eliminates the
xsl:for-each and uses XSLT 2.0's new "separator" attribute on xsl:value-of
as follows:
<xsl:variable name="b" select="document('2.xml')/outsidedata/b
[every $att in @* satisfies current()/@*
[.=$att and name(.)=name($att)]]"/>
<xsl:if test="$b">
<xsl:text>[</xsl:text>
</xsl:if>
<xsl:value-of select="$b" separator="]
["/>
<!-- character reference is necessary -->
<xsl:if test="$b">
<xsl:text>]</xsl:text>
</xsl:if>
If you didn't need the outer delimiters (before the first item and after the
last item), you could get rid of the variable and xsl:if tests and simply
write:
<xsl:value-of select="document('2.xml')/outsidedata/b
[every $att in @* satisfies current()/@*
[.=$att and name(.)=name($att)]]"
separator=","/>
Evan
> On Mon, May 06, 2002 at 12:55:32AM -0700, Evan Lenz wrote:
> > [NOTE: XPath 2.0 is still in Working Draft stage, subject to
> change, and not
> > yet ready for prime time.]
> >
> > While the magical expression you want cannot be expressed in
> XPath 1.0, it
> > can easily be expressed in XPath 2.0:
> >
> >
> > document('2.xml')/outsidedata/b
> > [every $att in @* satisfies current()/@*
> > [.=$att and node-name(.)=node-name($att)]]
> >
> >
> > The "every" expression is called a universal quantifier[1] and
> enables you
> > to test that a condition applies for *every* node in a given
> sequence. This
> > is something that could not be done in general in XPath 1.0.
> >
> > The node-name() function[2] returns an "expanded QName" type
> that consists
> > of a local/URI pair that can in turn be compared with other
> expanded names.
> > This ensures that your code is robust in the face of namespace-qualified
> > attributes without having to write [local-name(.)=local-name($att) and
> > namespace-uri(.)=namespace-uri($att)]. This is a welcome
> shorthand indeed!
> >
> > Except for the node-name() function, I'm happy to report that a
> stylesheet
> > with this expression (using name() instead) is executed as
> expected by Saxon
> > 7.1. Below is the stylesheet I ran against your two files:
> >
> >
> > <xsl:stylesheet version="2.0"
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> >
> > <xsl:output method="text"/>
> >
> > <xsl:template match="/">
> > <xsl:apply-templates select="/mydata/a"/>
> > </xsl:template>
> >
> > <xsl:template match="/mydata/a">
> > <xsl:for-each select="document('2.xml')/outsidedata/b
> > [every $att in @* satisfies current()/@*
> > [.=$att and name(.)=name($att)]]">
> > <xsl:text>[</xsl:text>
> > <xsl:value-of select="."/>
> > <xsl:text>]</xsl:text>
> > <xsl:if test="position() != last()">
> > <xsl:text>
> > </xsl:text>
> > </xsl:if>
> > </xsl:for-each>
> > </xsl:template>
> >
> > </xsl:stylesheet>
> >
> >
> > Invocation and output:
> >
> > $ java net.sf.saxon.Transform 1.xml test.xsl
> > [PPP]
> > [QQQ]
> > [RRR]
> > $
> >
> > With your (corrected) reformulation of the original problem, I
> believe the
> > expression only needs slight modification (@* trades places with
> > current()/@*):
> >
> > document('2.xml')/outsidedata/b
> > [every $att in current()/@* satisfies @*
> > [.=$att and node-name(.)=node-name($att)]]
> >
> > Hope you found this helpful, or at least interesting!
> >
> > Evan
> >
> > [1] http://www.w3.org/TR/xpath20/#id-quantified-expressions
> > [2] http://www.w3.org/TR/xquery-operators/#func-node-name
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list