Reputation: 25
The sample presented is a simplified version of what I am trying to do.
Using XSLT, how do I compare data from nodes in different (non -child) xpaths? I want to compare each cd/artist
with the dvd/director
to see if they match (see samples below). There are multiple cd's and dvd's, but in this simplified example I only used one of each. I tried doing the comparison within one template, but I couldn’t access the dvd xpath. And I couldn't access the dvd xpath by using a separate template. When using a separate template, I created a 'compare' template that I called (<xsl:call-template name="compare">
). By access, I mean that I couldn't print out the dvd/director's value.
My Question: How do I access one xpath when accessing a different xpath? What I want to do is compare cd artist with dvd director to see if they match. And print out these values, if they match. What I can't figure out is how to get the artist and director so I can compare them. My xslt does print the cd's artist value, but I can't print out the dvd/director's value.
My samples follows:
The samples come from W3Schools. I modified them to illustrate my question.
Sample XSLT
<xsl:for-each select="catalog/cd">
<xsl:value-of select="@artist"/>
<xsl:for-each select="catalog/dvd">
<xsl:if test="@director = @artist">
<xsl:value-of select="@director"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
Sample XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd title="Unchain my heart" artist="Joe Cocker">
<country>USA</country>
<company>EMI</company>
<price>8.20</price>
<year>1987</year>
</cd>
<dvd title="My DVD Movie" director="Joe Cocker">
<country>USA</country>
<company>WB</company>
<price>20.00</price>
<year>1999</year>
</dvd>
</catalog>
Thanks for your help in advance.
Upvotes: 2
Views: 208
Reputation: 60414
I think the larger issue is that you're thinking in procedural terms, which is rarely the right way to approach a problem with XSLT. A better way is to first match cd
elements and then select the dvd
elements whose director
matches the artist
. Consider this stylesheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/*/cd">
<xsl:value-of select="artist"/>
<xsl:apply-templates select="../dvd[director=current()/artist]"
mode="out"/>
</xsl:template>
<xsl:template match="dvd" mode="out">
<xsl:value-of select="director"/>
</xsl:template>
<xsl:template match="dvd"/>
</xsl:stylesheet>
The first template applies templates to all dvd
elements for which the following predicate evaluates to true: director=current()/artist
Of course, as in your example, we're just printing the name Joe Cocker
twice, which isn't very useful.
Note: This approach breaks down when there is more than one cd
element with the same artist
. More complicated grouping strategies would address that case.
Upvotes: 1
Reputation: 26930
Well some pointers :
<xsl:for-each select="catalog/cd">
When you are doing this you are "inside" each catalog/cd element. Therefore your current() represents eacy catalog/cd element.
Your "comparison function" :
<xsl:if test="@director = @artist">
Does not work since you are trying to compare attributes director and artist. But there are not director and artist attributes, and even if they were, you would be trying to compare the attributes of catalog/dvd
.
So the dvd element would have had to be like <dvd director="foo" artist="bar"/>
etc..
I guess that what you are really trying to do is finding cd's and dvd's which have the same artist/director. It is not clear to me what you are trying to achieve. If you elaborate you will get a better answer.
Upvotes: 0
Reputation: 52878
You can simplify your for-each
and use current()
...
<xsl:for-each select="catalog/cd">
<xsl:value-of select="artist"/>
<xsl:for-each select="../dvd[director = current()/artist]">
<xsl:value-of select="director"/>
</xsl:for-each>
</xsl:for-each>
Upvotes: 0
Reputation: 2167
Make that:
<xsl:for-each select="/catalog/dvd">
Without the leading slash "/", catalog/dvd is relative to the current node,
which is set by <xsl:for-each select="catalog/cd">
Upvotes: 0