Subject: Re: [xsl] Identifying two tags that share some attribute names and values From: Zack Brown <zbrown@xxxxxxxxxxxxxxx> Date: Sun, 5 May 2002 10:08:50 -0700 |
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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Identifying two tags that, Jeni Tennison | Thread | Re: [xsl] Identifying two tags that, Joerg Heinicke |
Re: [xsl] Which has priority xml:sp, Oleg Tkachenko | Date | RE: [xsl] Finding the lowest 'price, Michael Kay |
Month |