This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: Identifying two tags that share some attribute names and values - XPATH 2.0 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="]&#xA;["/>
>                <!-- character reference is necessary -->
>     <xsl:if test="$b">
>       <xsl:text>]</xsl:text>
>     </xsl:if>
>

Which you can reduce further to:

<xsl:variable ... as before .../>
<xsl:if test="$b">[<xsl:value-of select="$b" 
                     separator="]&#xA;["/>]</xsl:if>

Michael Kay
Software AG
home: Michael.H.Kay@ntlworld.com
work: Michael.Kay@softwareag.com 


> 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
> 

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]