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


Wow, a very simple solution! I think I won't use it right away, because I want
to use only tools that are readily available on most Linux distributions,
in case other folks want to experiment with my stylesheets. I've been using
xsltproc so far, and that seems to handle everything I've tried to use. But
I'll save this recipe for when 2.0 comes out, or when Debian packages start
supporting the draft.

Is there a general consensus that XPath and XSLT are moving in the right
direction, or will future standards lay waste to what I consider to be a
very elegant system?

Thanks!
Zack

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
> 
> 
> > -----Original Message-----
> > From: owner-xsl-list@lists.mulberrytech.com
> > [mailto:owner-xsl-list@lists.mulberrytech.com]On Behalf Of Zack Brown
> > Sent: Saturday, May 04, 2002 11:08 AM
> > To: xsl-list@lists.mulberrytech.com
> > Subject: [xsl] Identifying two tags that share some attribute names and
> > values
> >
> >
> > Hi folks,
> >
> > I've been migrating the Kernel Traffic web site
> > (http://kt.zork.net) 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:  http://www.mulberrytech.com/xsl/xsl-list
> >
> >
> 
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 

-- 
Zack Brown

 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]