Bug 7844

Summary: <x:forEach> Doesn't Iterate Properly
Product: Taglibs Reporter: David Geary <sabreware>
Component: Standard TaglibAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED INVALID    
Severity: normal    
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: Other   
OS: Windows XP   

Description David Geary 2002-04-08 15:20:33 UTC
I have this code ...

<x:forEach select="$addressBook/*"> 
   ADDRESS
</x:forEach>

... which produces this output ...

ADDRESS

... for this XML file:

<addressBook>
   <address>
      <firstName>Anna</firstName>
      <lastName>Keeney</lastName>
      <email>anna.keeney@worldlink.net</email>
      <phone type="work">716-873-9644</phone>
      <phone type="home">716-834-8772</phone>
   </address>
   <address>
      <firstName>Ronald</firstName>
      <lastName>Dunlap</lastName>
      <email>ron.dunlap@worldlink.net</email>
      <phone type="work">716-873-9644</phone>
      <phone type="home">716-834-8772</phone>
   </address>
</addressBook>

The output, as far as I can tell, should be ...

ADDRESS
ADDRESS

... because there are 2 addresses in the file.
Comment 1 Shawn Bayern 2002-04-08 15:35:12 UTC
No, <x:forEach> is behaving properly.

I think you're misunderstanding the mechanism.  You're apparently assuming that 
the scoped variable "addressBook" refers somehow to a tree where the context
node is the root element.  Instead, the variable refers to the entire parsed
tree.  Thus, the single "ADDRESS" that's printing corresponds to the single 
document root element:  <addressBook> ... </addressBook>.  If you want to
loop over each <address> ... </address> element, you'll need to use an 
expression like

 $addressBook/addressBook/*

This might look odd to you at first, but I'd assert that's just because you 
used the same name for the scoped variable and the root element of your 
document.

To learn more about the mechanism, instead of printing just "ADDRESS," print a 
property of the context node (e.g., the tag name).  The behavior of <x:forEach> 
is demonstrated nicely in JSTL's standard-examples application.  (*Please* 
consult it before submitting bug reports.)  :-)  Thanks!