AEM/CQ: Capture each part of page path in an array - jstl

I have a CQ / AEM site.I am pretty new to AEM
I am doing a page depth function call.
<c:set var="pageDepth" value="<%= currentPage.getDepth() %>"/>
Path is
<c:set var="path" value="<%= properties.get("path", currentPage.getPath()) %>"/>
Path is
/content/my-blueprint/homepage/subpage/subpage1
I want to capture each part of path in a data structure (array/linked list) like
array[0] should be content and array[2] should be homepage etc..
Is there a way I can do it?

You can split the path on the / character.
You can do it java-style in the scriptlet:
<c:set var="pathArray" value="<%= properties.get("path", currentPage.getPath()).split("/") %>"/>
or JSTL-style:
<c:set var="pathArray" value="${fn:split(path, '/')}"/>
To access the array, you would do ${pathArray[2]}

Related

JSTL <c:if> tag to compare two variables

Why the block never reaches "conditionTrue"? I have printed both the variables
authorEmail and scase.authorEmail and they are same string. If I use literal like 'abc#yahoo.com' to test the condition , it works but not if both the c:if params are variables.
<c:forEach var="scase" items="${section.subSectionList.get(0).SCaseList}">
<c:set var="authorEmail" >
<sec:authentication property="principal.email" />
</c:set>
<c:if test = "${authorEmail == scase.authorEmail}" >
<option>conditionTrue</option>
</c:if>
</c:forEach>
UPDATE - I got it to work by making these changes.
I commented out the entire c:set tag. Instead I added these line -
<sec:authentication var="principal" property="principal" />
My test condition was then :
<c:if test = "${principal.email == scase.authorEmail}" >
<option>conditionTrue</option>
</c:if>
And this worked. However, the reasoning behind it still baffles me. Any insight, much appreciated.

How to compare two string in foreach loop of jsp/jstl?

I have the need to compare to strings in foreach loop.
My development environment:
1) MAC 10.11,
2) STS Version: 3.7.3.RELEASE
4) Spring Web MVC,
5) Pivotal tc Server Developer Edition v3.1
<c:set var="day" scope="session" value="${day}_${curId}"/>
<c:set var="new_day" scope="session" value="${2_456123}"/>
<c:if test="${day eq new_day}">
<p> Both are same.
</c:if>
But the system get hags at the line
<c:if test="${day eq new_day}">
Can somebody give any pointer ?
Thanks & Regards,
Arun Dhwaj
Here is demonstration code.
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<c:set var="day" scope="session" value="2"/>
<c:set var="curId" scope="session" value="456123"/>
<c:set var="day" scope="session" value="${day}_${curId}"/>
<c:set var="new_day" scope="session" value="2_456123"/>
<c:if test="${day eq new_day}">
Both are same.
</c:if>
that prints: Both are the same.
If I change line number 5 to
<c:set var="new_day" scope="session" value="${2_456123}"/>
which is what you posted, then I get an error message
contains invalid expression(s): javax.el.ELException: Failed to parse the expression [${2_456123}]
Most likely the problem is caused by the following assignment
<c:set var="day" scope="session" value="${day}_${curId}"/>
With the above line you are assigning to the var day a value that comes from another variable with the same name but not necessarily with the same scope. In other words you might have already a variable called day that lives in another scope.
The default scope is the page scope, then you have in order the request, session and application therefore if a variable with the name day is retrieved in the page or request scope that variable will be considered when you perform the test and the variable you have defined in the session scope will be ignored.
You have two options
Change the name of the variable defined in the session scope and use that name when performing the test
<c:set var="niceday" scope="session" value="${day}_${curId}"/>
<c:if test="${niceday eq ...}">
Specify the scope of the variable used in the c:if tag
<c:if test="${sessionScope.day eq ...}">
Hope that helped.

Java Server page

I have implemented the if / else tag in JSTL like following. But its not working. If condition not checking.
<c:choose>
<core:if ${capital.nextCapital()} eq ${request.capital}>
<p> Yes. The capital of ${capital.nextState()} is ${capital.nextCapital()} </p>
</core:if>
<c:otherwise>
<p>No. The capital of ${capital.nextState()} is ${capital.nextCapital()} </p>
</c:otherwise>
</c:choose>
That is not valid syntax at all.
the standard prefix is c, not core
inside c:choose, you can use c:when and c:otherwise. Not c:if.
the boolean condition must be inside a test attribute:
Attributes must be surrounded by quotes:
<c:when test="...">
The whole boolean EL expression must be inside ${}:
<c:when test="${ ... }">
So the end result should be
<c:when test="${capital.nextCapital() eq request.capital}"> ... </c:when>
I suggest you re-read your book or tutorial about custom tags and the JSTL.

jstl access a second array value with foreach index

i have two arrays (strings delimited with commas) and i made a foreach loop on one of this vars
i need to be able to access to the other string with the foreach index like
<c:set var="name" value="Zara,nuha,roshy" />
<c:set var="name2" value="Zara2,nuha2,roshy2" />
<c:forEach items="${name}" delims="," var="name" varstatus="i">
<c:out value="${name}"/><br>
</c:forEach>
i need to access name2 values, in the name foreach, is it possible without doing another foeach?
The varstatus variable you are using contains a value "index" that you can use.
But, you can't operate on a string like that (not that I know of at least).
First, you need to convert name2 to a proper array or list. Then you can access it inside the for loop:
${name2list[i.index]}
Now, how to convert it to an array? How about the split function?
<%#taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="name2list" value="${fn:split(name2, ',')}"/>
This can be done, contrary to some previous comments.
See the following example based on the question:
<c:set var="names" value="Zara,nuha,roshy" />
<c:set var="names2" value="Zara2,nuha2,roshy2" />
<c:forEach items="${names.split(',')}" varStatus="i" var="name" >
${name} : ${names2.split(',')[i.index]}<br/>
</c:forEach>
Essentially we're using a string split function with expression language to get a string array from list comma separated values. Within the loop we the get the second value from the names2 array by using the varStatus index. I believe this accomplishes the task.

Help with regex / ruby

Hey guys, so I'm making a script to featch words/results off of this site (http://grecni.com/texttwist.php), So I already have the http request post ready, ect.
Only thing I need now is to fetch out the words, So I'm working with an html source that looks like so:
<html>
<head>
<title>Text Twist Unscrambler</title>
<META NAME="keywords" CONTENT="Text,Twist,Text Twist,Unscramble,Free,Source,php">
</head>
<body>
<font face="arial,helvetica" size="3">
<p>
<b>3 letter words</b><br>sae sac ess aas ass sea ace sec <p>
<b>4 letter words</b><br>cess secs seas ceca sacs case asea casa aces caca <p>
<b>5 letter words</b><br>cacas casas caeca cases <p>
<b>6 letter words</b><br>access <br><br>
Found 23 words in 0.22962 seconds
<form action="texttwist.php" method="post">
enter scrambled letters and I'll return all word combinations<br>
<input type="text" name="l" value="asceacas" size="20" maxlength="20">
<input type="submit" name="button" value="unscramble">
<input type="button" name="clear" value="clear" onClick="this.form.l.value='';">
</form><p>
<a href=texttwist.phps>php source</a>
- it's kinda ugly, but it's fast<p>
<a href=/>back to my page</a>
</body>
</html>
I'm trying to fetch the words like "sae", "sav", "secs", "seas", "casas", ect.
Any help?
This is the farthest i've gotten, don't know what to do from here.: link text
Any suggestions? Help?
Use a HTML parser like Nokogiri.
If you want any kind of robustness you really want a parser, as mentioned by Adrian, Nokogiri is most popular solution.
If you insist, aware of the madness that you may be in for as the page becomes more complex the following may help:
Search for a line that matches
/^<b>\d+ letter words/
and then you can dig out the bits like so:
a = line.split(/<br>/)[1] # the second half
a.gsub!('<p>', '') # take out the trailing <p>
res = a.split(' ')# this is your data
That being said, this isn't anything you want in production code. You'll be surprised how learning a parser will change how you see this problem.

Resources