This question started as a post in the extending umbraco forum and now that I know how to conceptually tackle the problem and have choosen my plan of attack, I'm a bit confused as to how to approach it.
I am setting up blogs and on the homepage of each blog I need it to display the first 4 posts (no problem) but take the first post and display 4 paragraphs and every subsequent post only display 1. I want to acheive this by having the XSLT scan each node and display based on <p> tags.
This is part of the XSLT I have, and I know its incorrect - but I also know that I need to do something to the first post and something slightly different after but this is a bit over my very introductory knowledge of XSLT.
<span class="readMore"> <a href="{umbraco.library:NiceUrl($post/@id)}" title="Permalink to {$post/@nodeName}">Read More</a>
Any hints as to how to approach either selecting just the first post or to having the XSLT look inside the nodes for limited numbers of HTML tags would be hugely appreciated as it would help me out here and in other places on the site.
The reason that doesn't work is that: $post/data [@alias = 'bodyText'] refers to the XML file with the nodes in it and 'p' is not defined in the as anything in the the file ( it will be CDATA information which is a trigger to let it know it is not part of the XML file). Here is how a typical node in your umbracoSettings.config file looks (it is in your data folder):
Great idea! I did not realize that about the CDATA, but using a slightly altered version of your code I was able to get it to work for the first part of the problem.
With this, it prevented to the full closing p tag from escaping anything and causing a nasty error.
This solves the first and hopefully largest of the two issues. The second is this. I can get this to work perfectly and display the first paragraph of every entry. I, however, am completely baffled by how to solve the other issue:
The first entry needs to pull 3 or 4 paragraphs and I have no idea 1.) how to treat the first post differently and 2.) how to apply this logic to the fourth paragraph without having the editors add some sort of class or id tag attribute to the p tag.
What most people do I think is just have a character limit which is what you can do with substring and so you are just going to show the first 250 characters.
If it isn't possible just with those XSLT functions you may need to use some C# or javascript code in your XSLT in order to get those specific first 3 paragraphs:
The loop worked perfectly and I have figured out some pseudo code (which I'm attempting to, but struggling with turning into real code) but here's my logic...
final output = substring($post/data [@alias
='bodyText'],0,a)
Hopefully the logic makes sense, unfortunately since XSLT is very new to me I don't know how the syntax would work for this logic. That logic/pseudo code would be placed within the current loop so it is called whenever the position()=1. I'm looking into it now but ANY clues, hints or help would be greatly appreciated!
I have had partial success! I am able to get it to do everything I want but there is a major, semi-fatal flaw which I can't seem to find a solution to. If there is only one paragraph, it won't pull anything.
I know it's not a solution to your problem, but when doing this I just create a textboxmultiple field called "summary" that the authors can useto create short summaries for list pages etc.
I thought about doing something like that. The issue cropped up that the top article (newest) needs to show more than articles following it. Ugh. I may end up doing this though as a temporary solution.
I have come up with a solution. I don't believe it is ideal, but it works for my purposes until I find a better one. It has been tested a decent amount (I had my editors try to break it.) The only issue I have found is if they inadvertantly insert an empty p tag at the top it will mess things up until they go back and delete it. This will pull the top 4 paragraphs for the first blog post before it enters the loop to pull the first paragraph of the next few posts.
A bit late - but having just moved to Umbraco (after the learning curve I'm thanking my lucky stars I did cos its excellent) I have hit a similar wall.
Whilst slightly different from the posters original problem this solution extends the XSLT with C# in order to process paragraphs for a blog teaser. The substring method is certainly the easiest but means that the teaser can get cut off. Anayway - here is the code:
Put this section into your XSLT file: - **Please note that you will need to add the relevent prefix and msxml namespace to you xslt declaration but all of that is included in the link above.
Pulling first few <p> tags out of node
Hi,
This question started as a post in the extending umbraco forum and now that I know how to conceptually tackle the problem and have choosen my plan of attack, I'm a bit confused as to how to approach it.
Original post:
http://our.umbraco.org/forum/developers/extending-umbraco/6869-Displaying-Excerpts-and-a-multiblog-page-with-Blog4Umbraco
I am setting up blogs and on the homepage of each blog I need it to display the first 4 posts (no problem) but take the first post and display 4 paragraphs and every subsequent post only display 1. I want to acheive this by having the XSLT scan each node and display based on <p> tags.
This is part of the XSLT I have, and I know its incorrect - but I also know that I need to do something to the first post and something slightly different after but this is a bit over my very introductory knowledge of XSLT.
Any hints as to how to approach either selecting just the first post or to having the XSLT look inside the nodes for limited numbers of HTML tags would be hugely appreciated as it would help me out here and in other places on the site.
Thanks
Something like this does not appear to work but I'm not sure why...
The reason that doesn't work is that: $post/data [@alias = 'bodyText'] refers to the XML file with the nodes in it and 'p' is not defined in the as anything in the the file ( it will be CDATA information which is a trigger to let it know it is not part of the XML file). Here is how a typical node in your umbracoSettings.config file looks (it is in your data folder):
As you can see the <p> is inside the CDATA and so will not be in your Xpath.
I think a better route for you would be some string methods. substring-before will work when you just need the one paragraph:
http://www.zvon.org/xxl/XSLTreference/Output/function_substring-before.html
You could do something similar to this (gets the substring of everything before the first </p>:
<xsl:value-of select="substring-before ($post/data [@alias = 'bodyText'],'</p>')" />
Hi Seth,
Great idea! I did not realize that about the CDATA, but using a slightly altered version of your code I was able to get it to work for the first part of the problem.
With this, it prevented to the full closing p tag from escaping anything and causing a nasty error.
This solves the first and hopefully largest of the two issues. The second is this. I can get this to work perfectly and display the first paragraph of every entry. I, however, am completely baffled by how to solve the other issue:
The first entry needs to pull 3 or 4 paragraphs and I have no idea 1.) how to treat the first post differently and 2.) how to apply this logic to the fourth paragraph without having the editors add some sort of class or id tag attribute to the p tag.
in your for loop you can use the position() to figure out where you are at:
<xsl:choose>
<xsl:when test="position()= 1" >
extra stuff for your first one.
</xsl:when>
</xsl:choose>
As to what to do inside there. Maybe you can figure out some way to only get the first 3 paragraphs with a combination of the string functions: http://www.w3schools.com/Xpath/xpath_functions.asp.
What most people do I think is just have a character limit which is what you can do with substring and so you are just going to show the first 250 characters.
If it isn't possible just with those XSLT functions you may need to use some C# or javascript code in your XSLT in order to get those specific first 3 paragraphs:
http://umbraco.org/documentation/books/extending-xslt-with-c-sharp-or-javascript/why-extend-xslt
Thanks a lot Seth. This looks like a great place to start and maybe I will be forced to go the character route. I'll let you know what I end up with.
Seth, the loop worked perfectly so now I'm looking further into XPath. I'll post the final loop when I'm done since it might be helpful.
Hey Seth,
The loop worked perfectly and I have figured out some pseudo code (which I'm attempting to, but struggling with turning into real code) but here's my logic...
Current Loop:
My logic is:
string-length($post/data [@alias = 'bodyText']) = a
b=string-length(substring-after($post/data [@alias ='bodyText'],</p>))
if (b != 0) then{
a = a-b
b=string-length(substring-after(substring($post/data [@alias ='bodyText'],a,string-length($post/data [@alias = 'bodyText'])),</p>))
if(b != 0) then{
a = a+b
b=string-length(substring-after(substring($post/data [@alias ='bodyText'],a,string-length($post/data [@alias = 'bodyText'])),</p>))
}}then
final output = substring($post/data [@alias ='bodyText'],0,a)
Hopefully the logic makes sense, unfortunately since XSLT is very new to me I don't know how the syntax would work for this logic. That logic/pseudo code would be placed within the current loop so it is called whenever the position()=1. I'm looking into it now but ANY clues, hints or help would be greatly appreciated!
Thanks
Hi Everyone,
I have had partial success! I am able to get it to do everything I want but there is a major, semi-fatal flaw which I can't seem to find a solution to. If there is only one paragraph, it won't pull anything.
This is my current code
I've tryied adding an if statement in using the firstPostLength variable as shown below
and that then displays nothing. I don't know why.
Any ideas? It's almost there.
I spoke too soon. That solution is full of issues. It only worked because my content was too short! Wishful thinking for the morning.
I know it's not a solution to your problem, but when doing this I just create a textboxmultiple field called "summary" that the authors can useto create short summaries for list pages etc.
It's simple and bulletproof, and won't cause madness from parsing html with regexes and other such things.
But, a solution to this would be interesting.
Dan
Hi Dan,
I thought about doing something like that. The issue cropped up that the top article (newest) needs to show more than articles following it. Ugh. I may end up doing this though as a temporary solution.
Andrew
Hello Everyone,
I have come up with a solution. I don't believe it is ideal, but it works for my purposes until I find a better one. It has been tested a decent amount (I had my editors try to break it.) The only issue I have found is if they inadvertantly insert an empty p tag at the top it will mess things up until they go back and delete it. This will pull the top 4 paragraphs for the first blog post before it enters the loop to pull the first paragraph of the next few posts.
Hope this helps someone else and if i ever find a better solution I'll post it
Hi,
A bit late - but having just moved to Umbraco (after the learning curve I'm thanking my lucky stars I did cos its excellent) I have hit a similar wall.
Whilst slightly different from the posters original problem this solution extends the XSLT with C# in order to process paragraphs for a blog teaser.
The substring method is certainly the easiest but means that the teaser can get cut off. Anayway - here is the code:
You will need to modify your XSLT file as per the instructions here:
http://umbraco.org/documentation/books/extending-xslt-with-c-sharp-or-javascript/extending-using-c-sharp
Put this section into your XSLT file: - **Please note that you will need to add the relevent prefix and msxml namespace to you xslt declaration but all of that is included in the link above.
Then call this function with the blogBody text and it will return (in this case, a dodgy hard coded first 3 paragraphs)
is working on a reply...