RE: [xsl] Identifying two tags that share some attribute names and values - XPATH 2.0 SOLUTION

Subject: RE: [xsl] Identifying two tags that share some attribute names and values - XPATH 2.0 SOLUTION
From: "Evan Lenz" <evan@xxxxxxxxxxxx>
Date: Mon, 6 May 2002 00:55:32 -0700
[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:

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

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:apply-templates select="/mydata/a"/>

  <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:value-of select="."/>
      <xsl:if test="position() != last()">


Invocation and output:

$ java net.sf.saxon.Transform 1.xml test.xsl

With your (corrected) reformulation of the original problem, I believe the
expression only needs slight modification (@* trades places with

    [every $att in current()/@* satisfies @*
         [.=$att and node-name(.)=node-name($att)]]

Hope you found this helpful, or at least interesting!



> -----Original Message-----
> From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> [mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of Zack Brown
> Sent: Saturday, May 04, 2002 11:08 AM
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Identifying two tags that share some attribute names and
> values
> Hi folks,
> I've been migrating the Kernel Traffic web site
> ( over to an
> XML/XSLT-based production system. So far it looks like something
> I should have
> done years ago. Compilation time (compared with my old home-grown
> processor)
> has dropped from hours to minutes, and the flexibility to add new features
> is just amazing.
> However, there are still a few things that are giving me
> problems. One such
> boils down to trying to identify a set of tags that share attributes with
> a target tag. So for instance I have two files, 1.xml and 2.xml:
> ----------------------------- 1.xml ---------------------------------
> <?xml version="1.0" ?>
> <mydata>
> <a x="1" y="2" z="3">test</a>
> </mydata>
> ---------------------------------------------------------------------
> ----------------------------- 2.xml ---------------------------------
> <?xml version="1.0" ?>
> <outsidedata>
> <b x="1" y="2">PPP</b>
> <b y="2" z="3">QQQ</b>
> <b z="3">RRR</b>
> <b x="9" y="8" z="7">SSS</b>
> <b m="2" z="3">TTT</b>
> </outsidedata>
> ---------------------------------------------------------------------
> Basically, 1.xml represents a newsletter file, and 2.xml is an
> automatically
> generated file that contains cross-reference information. The <a> tag in
> 1.xml is a cross-reference request that needs to be resolved using data
> available in 2.xml.
> processing is done on 1.xml, which reads in 2.xml via the document()
> function. The XSLT code analyzes 2.xml and looks for all <b> tags whose
> attributes precisely match attributes found in the target <a>
> tag. Note that
> not all of <a>'s attributes must be present in a matching <b>, but all of
> <b>'s attributes must be present in <a> and must share the same values as
> the corresponding attributes in <a>. Also note that <a>'s
> attributes are not
> necessarily "x", "y", and "z", but could be anything. The XSLT code should
> not make assumptions about their names or how many there may be.
> So in the above example files, <a> contains attributes "x", "y", and "z",
> which each have the values "1", "2", and "3" respectively.
> Looking at 2.xml,
> you can see that the first, second and third <b> tags are
> successful matches,
> while the fourth and fifth are not.
> What I need is a recipe like the following (except that works ;-):
> ----------------- XSLT code for processing a.xml --------------------
> <!-- Resolve kcrefs -->
> <xsl:template match="mydata/a">
> <xsl:for-each select="document('2.xml')/outsidedata/b">
> [<xsl:value-of select="."/>]
> </xsl:for-each>
> </xsl:template>
> ---------------------------------------------------------------------
> in which the output would look something like this:
> ----------------------- Desired output ------------------------------
> [PPP]
> [QQQ]
> [RRR]
> ---------------------------------------------------------------------
> I hope I've described this well enough. I don't even know if it's possible
> to do what I'm asking for, though it seems like it should be. Any
> help would
> be greatly appreciated.
> Many thanks,
> Zack
> --
> Zack Brown
>  XSL-List info and archive:

 XSL-List info and archive:

Current Thread