how to implement this pattern using JSP - java

I'm new to using JSP and need to figure out how to do this. I'd appreciate any pointers on how to do this ?
I need to display images in this table-like structure. To simplify the problem,
A B C
D E F
G H I
where each of these elements are a part of the Set names in action class.
Set<String> names = new HashSet<String>(0);
names.add("A");
names.add("B");
names.add("C");
names.add("D");
names.add("E");
names.add("F");
names.add("G");
names.add("H");
names.add("I");
Its fairly trivial to do it in java, however, I am having a hard time to figure out, how do I ask the iterator to point to next element manually.
<s:iterator value="names">
<s:property/>
I'd now like to point iterator to point to next or run a nested iterator loop here.
</s:iterator>

You can use JSTL forEach loop. You can find a number of examples here.

You can easily accomplish it with JSTL:
<table>
<tr>
<c:forEach items="names" var="name" varStatus="i">
<c:if test="${!i.first && !i.last && i.index % 3 == 0}">
</tr>
<tr>
</c:if>
<td><c:out value="${name}" /></td>
</c:forEach>
</tr>
</table>
Doing so, a new line (</tr><tr>) will be added every 3 elements.
(not tested)

As CoolBeans said, you can use JSTL forEach loop.
If you'd like to see an example of that (alongside other good JSTL examples), check out JSTL Examples.
"Iterating over data structures" has some info and examples on what you're trying to do.

Related

Syntax error on selenium xpath expression

I'm building a selenium findElement by.xpath expression, very complex, and it appears there is a syntax error.
I don't really know XML language so I made mistake(s) obviously, could someone tell where are the mistake(s) ? :)
Thanks!
I have a list of projects on a web page, in each project there are sub-projects, I want a specific one, I know the name and the subName.
The html code is something like :
<table id="list_proj" class="table tablebas table-striped table-bordered">
<thead>
<tbody style="height:1em;overflow-y:scroll"></tbody>
<tbody style="height:1em;overflow-y:scroll"></tbody>
<tbody style="height:1em;overflow-y:scroll">
<tr class="caption">
<td class="app_name" style="background-color:#EFEFEF;" colspan="11">
<b>
Application SEVo
</b>
</td>
</tr>
<tr class="data"></tr>
<tr class="data"></tr>
<tr class="data">
<td title="Pas de commentaire !" style="text-align:left">
<img alt="MCO" src="/colibri/images/corner-dots.gif"></img>
MCO
</td>
<td>0.50</td>
<td></td>
<td colspan="2">
</tr>
<tr class="data">
</tbody>
<tbody style="height:1em;overflow-y:scroll"></tbody>
</table>
And my xpath expression :
driver.findElement(
By.xpath(
"((//a[contains(text(),'"+name+"')])[1]
.(ancestor::td[#class='caption'])[1]
.following-sibling::td[#class='data']
.descendant::(a[contains(text(),'"+subName+"')])[1])[1]"
));
Sorry for the mess ^^'
Use below xPath which is more better :-
//a[contains(.,'"+name+"')]/ancestor::tr/following::a[contains(.,'"+subName+"')]
for eg. :- //a[contains(.,'Application SEVo')]/ancestor::tr/following::a[contains(.,'MCO')]
Updated..
another one is :-
//a[contains(.,'"+name+"')]/following::a[contains(.,'"+subName+"')]
Hope it will help you..:)
I don't know xPath with selenium, but I think the syntax error should be in the line below
.descendant::(a[contains(text(),'"+subName+"')])[1])[1]
Should be
.descendant::(//a[contains(text(),'"+subName+"')])[1])[1]
? (note the "//a")
It should be something like:
//a[contains(text(),'"+name+"')]/ancestor::tr[#class='caption']/following-sibling::tr[#class='data']//a[contains(text(),'"+subName+"')]
Don't use index [1] everytime, If you are sure that only one element would be returned, there is no point of putting index in every descendant or ancestor call.
"((//a[contains(text(),'"+name+"')])[1]
.(ancestor::td[#class='caption'])[1]
.following-sibling::td[#class='data']
.descendant::(a[contains(text(),'"+subName+"')])[1])[1]"
There's so much wrong with this it's hard to know where to start. First, we don't know what's in the variables name and subName - if these strings contain single quotes then anything might happen (injection attack). Secondly, it seems to be using "." as a separator between steps in the path when it should use "/". Third, what follows an axis like "descendant::" must be a NodeTest, and that rules out a parenthesized expression.
I think there's a real problem in your approach. Writing a complex expression in a language you don't understand and then asking on SO what the syntax errors mean is not going to be a good way to make progress. (Once you've got rid of the syntax errors, will you then know what the XPath actually means?). Do some reading and learn the language properly; don't try to drive a car without taking driving lessons.

Why this if statment into a Spring MVC JSP page can't work?

I am pretty new in Spring MVC and JSP page and I have the following problem.
Into a controller class I add these 2 collections to my model object:
List<Integer> numeroProgettiWifiScuoleList = new ArrayList<>();
List<Integer> numeroProgettiPnsdScuoleList = new ArrayList<>();
by these lines:
model.addAttribute("numeroProgettiWifiScuoleList", numeroProgettiWifiScuoleList);
model.addAttribute("numeroProgettiPnsdScuoleList", numeroProgettiPnsdScuoleList);
And it works fine. The problem is that now into my JSP page I have something like this:
<c:forEach items="${listaScuoleDS}" var="scuola" varStatus="item">
<c:if test="${numeroProgettiWifiScuoleList[item.index] == 0}">
<p>Nessun progetto WIFI associato alla scuola</p>
</c:if>
</c:forEach>
So, as you can see, into the forEach cycle I have to perform an if test that check if the value of the numeroProgettiWifiScuoleList collection related to the current item in the iteration (item.index) is equal to 0. In this case show a text.
But in this way don't work (the tag is not shown).
Why? What am I missing? How can i fix this issue?
You have to give the var name in IF condition..Because you are using JSTL tag to get the value.
<c:set var ="numeroProgettiWifiScuoleList" value=${numeroProgettiWifiScuoleList}">
<c:forEach items="${listaScuoleDS}" var="scuola" varStatus="item">
<c:if test="${scuola[item.index] == 0}">
<p>Nessun progetto WIFI associato alla scuola</p>
</c:if>
</c:forEach>

JSTL - accessing cookies

Hello everyone,
I was just wondering whether it's possible to access all the stored cookies like this:
<c:forEach items="${cookie}" var="currentCookie" varStatus="lp">
<tr><td>${cookie[lp.index].key} </td></tr>
</c:forEach>
if not, is there any way I could somehow itterate over cookies and other array in one loop?
<c:forEach items="${cookie}" var="currentCookie" varStatus="lp">
<tr><td>${CurrentCookie.key} </td></tr>
<tr><td>${MyArray[lp.index].name} </td></tr>
</c:forEach>
Thanks for any suggestions,
Wrack
Yes you can interate over cookies using JSTL for each, its similar like iterating over a map.
Similar question Retrieving cookie and array values in JSTL tags

Concatenating JSTL

I have a HashMap in the controller:
HashMap<String, ArrayList<String> map = new HashMap<String, ArrayList<String>();
In the JSP page I want to access this through something like this:
<c:forEach var="list" items="${requestScope.list}">
<c:set var="testing" value="{requestScope.map}"></c:set>
<c:forEach var="anotherTesting" items="${testing['${list.item}']}">
<option><c:out value="${anotherTesting}"/></option>
</c:forEach>
</c:forEach>
Where list.item is a String but it is used for another process but I want it to be used to access the HashMap.
Is there a way to concatenate JSTL? Either map.key or map['key'] will do.
I guess simply this would work:
<c:forEach var="anotherTesting" items="${testing[list.item]}">
<option><c:out value="${anotherTesting}"/></option>
</c:forEach>
Notice the difference with and without quotes:
${testing[list.item]} is equivalent to testing.get(list.getItem());
${testing['list.item']} is equivalent to testing.get("list.item");.
Some Note:
You don't need to specify the scope to access the attributes, unless there is a conflict with the same name in different scopes. So, "${requestScope.list}" can be changed to ${list}, and "${requestScope.map}" can be changed to ${map}.
Please use a different name for var attribute of outer loop. May be listItem instead of list.
No need to set the map to a different variable. That <c:set...> is not needed. You can directly access the property of map attribute.
So, your loop can be modified to:
<c:forEach var="listItem" items="${list}">
<c:forEach var="anotherTesting" items="${map[listItem.item]}">
<option><c:out value="${anotherTesting}"/></option>
</c:forEach>
</c:forEach>
The code in ${...} is not JSTL but Expression Language. You don't need to c̶o̶n̶c̶a̶t̶e̶n̶a̶t̶e̶ nest EL ${} expressions, just add it cleanly.
Knowing this, the expression ${testing['${list.item}']} will be ${testing[list.item]}.
BUT note that this is not what you really want/need unless testing is indeed a Map<String, ArrayList<String>>, otherwise you will get unexpected results. From your code above, assuming requestScope.list is a List<Map<String, ArrayList<String>>>, then the code would be:
<c:forEach var="listItem" items="${list}">
<c:forEach var="innerString" items="${map[listItem.item]}">
<option><c:out value="${innerString}"/></option>
</c:forEach>
</c:forEach>
Note that ${list} is the same as ${requestScope.list} assuming there's no list attribute nor in page, session or application scope, similar for ${map}.

Converting an ArrayList<someObjects> to an HTML table

I have a couple of ArrayLists with variable length and sometimes null. This ArrayList contains a bunch of objects.
The table should have columns based on (some) attributes of the object. And the table should be displayed on a jsp.
I have two ideas, one is to use a JSTL tag the other is to use JavaScript. And library suggestions are welcome.
JSTL is the standard, preferred way (unless you need to load it via ajax, for example)
<table>
<tr><td>Foo header</td><td>Bar header</td></tr>
<c:forEach items="${yourRequestScopedArrayList}" var="obj">
<tr>
<td>${obj.foo}</td>
<td>${obj.bar}</td>
</tr>
</c:forEach>
</table>
JSTL is better,
Javascript you should avoid as much as possible ,
I am not sure how you are going to render datatable using java script and Collection
How to use jstl with collection that has been demonstrated by Bozho in the same thread.
Javascript doesn't have access to the Java objects that live (I presume) on the server. The server code can make the ArrayLists available to the JSP which can then loop over them with a JSTL forEach tag.
How you make the ArrayLists "available" depends on the framework you're using, but the plain servlet way is just setting an attribute from the doPost method.
request.setAttribute("list1", arrayList1);
The loop would be something like
<table>
<tr><th>Column 1</th> <th>Column 2</th> <th>Column 3</th></tr>
<c:forEach var="row" items="${list1}">
<tr><td>${row.col1data}</td> <td>${row.col2data}</td> <td>${row.col3data}</td></tr>
</c:forEach>
</table>

Categories