views:

80

answers:

2

I have XSLT 1.0 code like this:

<xsl:key name="enemyItems"
         match="metadata[attributes/metadata_key/@value = 'enemylist']"
         use="attributes/metadata_refkey/@value"/>

<xsl:template match="item">
    <xsl:variable name="enemyList"
                  select="key('enemyItems', @key)/attributes/@value"/>
    <xsl:if test="string-length($enemyList) > 0">
        <xsl:value-of select="@name"/>
    </xsl:if>
</xsl:template>

As I understand it, a key can store more than one value for a particular element. I believe the code above is only getting the first value when referring to key('enemyItems', @key).

So, I want to wrap that code in an xsl:for-each, like this

    <xsl:template match="item">
        <xsl:for-each select="key('enemyItems', @key)">
            <xsl:variable name="enemyList"
                      select="???/attributes/@value"/>
            <xsl:if test="string-length($enemyList) > 0">
                <xsl:value-of select="@name"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

My question is: What goes in the ??? part? (That is, what is the name of the iteration variable or thing?)

A: 

As I understand it, a key can store more than one value for a particular element

No. A key may map a value with more than one node.

So, here:

<xsl:variable name="enemyList"  
              select="key('enemyItems', @key)/attributes/@value"/>  
<xsl:if test="string-length($enemyList) > 0">  
    <xsl:value-of select="@name"/>  
</xsl:if>

You're saying: let be $enemyList all the value attributes from attributes child elements from every node wich has a 'enemyItems' key with value equal to context node's key attribute, and if the string lenght of the string value from the first node in $enemyList node set is greater than 0, then output the value of context node's name attribute.

EDIT: In your second XSLT fragment:

<xsl:template match="item"> 
    <xsl:for-each select="key('enemyItems', @key)"> 
        <xsl:variable name="enemyList" 
                  select="???/attributes/@value"/> 
        <xsl:if test="string-length($enemyList) > 0"> 
            <xsl:value-of select="@name"/> 
        </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

Now, inside for-each, the context node is every node wich map with the key. So, you could define $enemyList like:

<xsl:variable name="enemyList" select="attributes/@value"/> 

This could also return several nodes if there ara more than one attributes child having a value attribute. But now, this:

<xsl:value-of select="@name"/> 

It's de name attribute of the context node... (the one wich map with the key)

Alejandro
Yes, but how do I get the other nodes in $enemyList node set (those other than the first)? That's what I'm asking.
Paul Reiners
@Paul Rainers: And what do you want to do with them? That's not clear from your question. Do you want to test that every node's string-value has a string-length greater than cero and then output **context node's `name` attribute**?
Alejandro
I want to know what I substitute in for the ??? part.
Paul Reiners
+1  A: 

Inside an xsl:for-each tag, the context on each iteration is the node being examined. Thus the ??? in your question should be replaced with .

Jim Garrison
Or nothing, as my answer. That explane why now `@name` (inside for-each) doesn't mean the same than before (outside for-each)
Alejandro