This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Identifying two tags that share some attribute names and values
Hi,
There's still a problem. when this recipe compares attributes, it sees
line-breaks within an attribute and uses them in its comparison. So <a x="hi
there"/> won't match <b x="hi there"/>.
Is there any way around this?
On Sun, May 05, 2002 at 10:08:50AM -0700, Zack Brown wrote:
> OUCH!
>
> I apologize for this, but it looks like I slightly misstated the problem. I
> tested your solution and it looks like exactly what I'm looking for, with one
> difference: it is not <a> that contains the superset of attributes, with <b>
> containing a subset. It's actually <b> that contains the superset, and <a>
> contains the subset.
>
> This variation seems to work for me:
>
> <xsl:variable name="file2" select="document('2.xml')/outsidedata"/>
> <xsl:template match="a">
> <xsl:variable name="a" select="." />
> <xsl:for-each select="$file2/b[@* = $a/@*]">
> <xsl:variable name="b" select="." />
> <xsl:variable name="test">
> <xsl:for-each select="$a/@*">
> <xsl:if test="not($b/@*[name() = name(current())] = .)">
> no attribute with the same name on element b whose value equals this one
> </xsl:if>
> </xsl:for-each>
> </xsl:variable>
> <xsl:if test="not(string($test))">
> [<xsl:value-of select="."/>]
> </xsl:if>
> </xsl:for-each>
> </xsl:template>
>
> Thanks!!
>
> Zack
>
> On Sun, May 05, 2002 at 11:01:25AM +0100, Jeni Tennison wrote:
> > Hi Zack,
> >
> > >> I didn't get it with one expression and need the step with $test:
> > >>
> > >> <xsl:variable name="file1" select="/"/>
> > >> <xsl:variable name="file2" select="document('2.xml')/outsidedata"/>
> > >>
> > >> <xsl:template match="/">
> > >> <xsl:apply-templates select="$file2/b"/>
> > >
> > > That's a problem, because 2.xml may contain thousands of entries,
> > > and I don't want to process each one. I just want to process the <a>
> > > from 1.xml and find any corresponding <b> in 2.xml.
> >
> > To search for a b element in 2.xml that matches your criteria, you're
> > going to have to process each of them in some way. I agree that's
> > going to be time-consuming given you have thousands of entries. There
> > are things that you could do to make it easier to search 2.xml --
> > rearrange the XML so that the bs are grouped by which attributes they
> > have, for example. Or carry out some filtering on 2.xml prior to using
> > it with XSLT.
> >
> > If you prefer to think of it as processing the a element, then have a
> > template that matches the a element, then you could do so:
> >
> > <xsl:template match="a">
> > <xsl:variable name="a" select="." />
> > <xsl:for-each select="$file2/b[@* = $a/@*]">
> > <xsl:variable name="test">
> > <xsl:for-each select="@*">
> > <xsl:if test="not($a/@*[name() = name(current())] = .)">
> > no attribute with the same name on element a whose value
> > equals this one
> > </xsl:if>
> > </xsl:for-each>
> > </xsl:variable>
> > <xsl:if test="not(string($test))">
> > <xsl:text />[<xsl:value-of select="." />]<xsl:text />
> > </xsl:if>
> > </xsl:for-each>
> > </xsl:template>
> >
> > Three minor variations on Joerg's solution here. First, I filter the b
> > elements that you iterate over to only those that have an attribute
> > whose value matches one of the attributes on a. That's just a rough
> > filter, and it won't lower the number of visits to b elements overall,
> > but it will prevent you from building up the $test variable for every
> > one of them.
> >
> > Second, the test in the middle is a bit simpler. Joerg used:
> >
> > $file1/a/@*[name()=name(current())][. != current()] or
> > not($file1/a/@*[name()=name(current())])
> >
> > which returns true if there is an attribute on a with the same name as
> > the attribute on b that you're looking at whose value is not equal to
> > the attribute on b *or* there's no attribute on a with the same name
> > as the attribute on b that you're looking at.
> >
> > The one I've used above is:
> >
> > not($a/@*[name() = name(current())] = .)
> >
> > which returns true if it is not the case that there is an attribute on
> > a, with the same name as the attribute on b that you're looking at,
> > whose value is the same as the attribute on b. This will therefore
> > return true either if the attribute on a with the same name isn't
> > equal to the value of the attribute on b, or if there's no attribute
> > on a with the same name.
> >
> > The second slight difference is in the value created for the $test
> > variable. All that you need to test here is whether $test ends up
> > having some content or not -- the only way it can have content is if
> > the test were true for one of the attributes, so you can use
> > test="not(string($test))" (does the $test variable not have a string
> > value?). Because of this, I tend to use something meaningful as the
> > string within the test -- here "no attribute with the same name on
> > element a whose value equals this one" because it documents what
> > you're doing a little and is helpful if you had to debug the code --
> > you could print out the value of $test and get a meaningful message.
> >
> > Cheers,
> >
> > Jeni
> >
> > ---
> > Jeni Tennison
> > http://www.jenitennison.com/
> >
> >
> > 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
>
--
Zack Brown
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list