How do I test if image exists for a field in xslt? - image

I have a form where a field is an image which is uploaded, which works fine. I now want to check to see if an image exists for that field and if not display a default no image
I have for now
<xsl:if test="fields/field_item_main_image/data/#original = ''"><span class="noimage"></span></xsl:if><xsl:copy-of select="fields/field_item_main_image/data" />
The span for no image simply provides a no image png file to be shown inplace of an image when none exists, but this is not working as the default image is not being shown, even though the field has no image assigned to it.
Looking at the source code the result is
<data></data>
What am I doing wrong?
ADDITIONAL INFO
I'd like to add more info but really not sure what you want me to add to help me... let me know what is needed and I will see if I can get that info for you to help me.
The relevant class style is
.noimage {display:block;width:100px;height:100px;background-image: url(../images/no-image-available.png);}
This is related to SobiPro a Joomla Compontent
Here is the form code
<div>
<xsl:for-each select="entry/fields/*">
<xsl:if test="( name() != 'save_button' ) and ( name() != 'cancel_button' )">
<xsl:variable name="fieldId">
<xsl:value-of select="data/*/#id" />
</xsl:variable>
<div id="{$fieldId}Container">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position() mod 2">spFormRowEven</xsl:when>
<xsl:otherwise>spFormRowOdd</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:if test="string-length( fee )">
<div class="spFormPaymentInfo">
<input name="{$fieldId}Payment" id="{$fieldId}Payment" value="" type="checkbox" class="SPPaymentBox" onclick="SP_ActivatePayment( this )"/>
<label for="{$fieldId}Payment">
<xsl:value-of select="fee_msg"></xsl:value-of><br/>
</label>
<div style="margin-left:20px;">
<xsl:value-of select="php:function( 'SobiPro::Txt', 'TP.PAYMENT_ADD' )" />
</div>
</div>
</xsl:if>
<div class="spFormRowLeft">
<label for="{$fieldId}">
<xsl:choose>
<xsl:when test="string-length( description )">
<xsl:variable name="desc">
<xsl:value-of select="description" />
</xsl:variable>
<xsl:variable name="label">
<xsl:value-of select="label" />
</xsl:variable>
<xsl:value-of select="php:function( 'SobiPro::Tooltip', $desc, $label )" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="label"/>
</xsl:otherwise>
</xsl:choose>
</label>
</div>
<div class="spFormRowRight">
<xsl:choose>
<xsl:when test="data/#escaped">
<xsl:value-of select="data" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="data/*" disable-output-escaping="yes"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text><xsl:value-of select="#suffix"/>
</div>
</div>
</xsl:if>
</xsl:for-each>
</div>
As part of the input one of my fields is an image field, it is that field I am wanting to check to see if a user has uploaded an image to that field, if they have then show that image, if not then show a default no image.
Does any of this help?
GW

If the default image for that field does not change, then I would do all of this on the client side.
Take a look at this answer to do that.

Related

Check if image exists in xslt

My task is to check if image exist and display it. Upper node is Hotel.
Xml file:
<PhotoList>
<Photo>
<Url>https://image.shutterstock.com/image-photo/hotel-word-golden-letters-
on-600w-378101848.jpg</Url>
</Photo>
<Photo>
<Url>http://demotest.itravelsoftware.com/fotografije_itravel/7/715_636077306767263022.jpg</Url>
</Photo>
<Photo>
<Url>http://demotest.itravelsoftware.com/fotografije_itravel/7/714_636077303419440444.jpg</Url>
</Photo>
<Photo>
<Url>http://demotest.itravelsoftware.com/fotografije_itravel/7/539_636064349608545756.jpg</Url>
</Photo>
</PhotoList>
Xslt:
<xsl:for-each select="PhotoList/Photo">
<xsl:choose>
<xsl:when test="Photo != ''">
<td><img src="Photo" height="100" width="100"/></td>
</xsl:when>
</xsl:choose>
</xsl:for-each>
This doesn't display picture and i'm not sure if != '' could properly check if img does or doesn't exists.
Maybe the code you are looking for is
<xsl:for-each select="PhotoList/Photo">
<xsl:choose>
<xsl:when test="normalize-space(Url) != ''">
<td><img src="{Url}" height="100" width="100"/></td>
</xsl:when>
</xsl:choose>
</xsl:for-each>
But it's only useful if there exist Photo elements with an empty Url child. The function normalize-space(Url) assures that Url elements with only whitespace content are handled as empty.

Similar type of data not matching the same case

I've the below XML
<?xml version="1.0" encoding="UTF-8"?>
<body>
<para><content-style font-style="bold">1/7 7.</content-style> This is First</para>
<para><content-style font-style="bold">1/8 8.</content-style> This is second<content-style format="superscript">6</content-style></para>
</body>
Here when i'm trying to apply template using my XSLT, though the above 2 paras are of same format, first is working and the second is not.
The expected output is as below.
<div class="para"><a name="P1-7"></a><span class="phrase">1/7</span> 7. This is First
</div>
<div class="para"><a name="P1-8"></a><span class="phrase">1/8</span> 8. This is second <span class="format-superscript">6</span>
</div>
and the current output that i get is
<div class="para"><a name="P1-7"></a><span class="phrase">1/7</span> 7. This is First
</div>
<para><span class="font-style-bold">1/8 8.</span> This is second<span class="format-superscript">6</span></para>
please let me know where am i going wrong and how to fix it.
Below is my XSL
<xsl:template match="para[content-style[matches(., '(\w+)/(\w+)')]][1]">
<div class="para">
<xsl:choose>
<xsl:when test="contains(substring-after(substring-after(./content-style/text(),'/'),'/'),' ')">
<xsl:analyze-string select="substring-before(.,' ')" regex="(\w+)/(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2),'-',regex-group(3))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
<xsl:text>     </xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
<xsl:choose>
<xsl:when test="./#format">
<span class="format-{#format}">
<xsl:value-of select="substring-after(.,' ')"/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:value-of select="substring-after(.,' ')"/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:analyze-string select="." regex="(\w+)/(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2),'-',regex-group(3))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
<xsl:text>     </xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template match="content-style">
<xsl:apply-templates select="./node()[1][self::page]" mode="first"/>
<xsl:choose>
<xsl:when test="./#format">
<span class="format-{#format}">
<xsl:apply-templates/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:apply-templates/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Working DEmo
Thanks
If you don't want the first paragraph only, don't request it.
para[content-style[matches(., '(\w+)/(\w+)')]][1]
^
|
here
Remove the quantifier and insert it into another expression as indicated:
contains(substring-after(substring-after(./content-style[1]/text(),'/'),'/'),' ')
^
|
here

XSLT dynamic sort using variables

I am trying to do dynamic sort based on values passed from the dropdown list. I am setting them as variables and using them in sort.
I am using XSLT version 1.0.
Below is the code:
test.php file -
<?php
mysql_connect('localhost','root','') or die(mysql_error());
mysql_select_db('testxslt');
$xml = new SimpleXMLElement( "<?xml version='1.0' ?>\n".
"<?xml-stylesheet type='text/xsl' href='xml_stylesort.xsl' ?>\n".
"<items></items>");
$_POST['sort_by']='price_desc';
//for sorting
if(isset($_POST['sort_by']) && !empty($_POST['sort_by'])){
$arr = explode('_', $_POST['sort_by']);
if($arr[1] == "asc") $sortorder = 'ascending';
if($arr[1] == "desc") $sortorder = 'descending';
// xml_appendNode($objXmlDom, $objDocNode, "sortby",$arr[0]);
$xml->addChild( "sortby",$arr[0]);
$xml->addChild( "sortorder",$sortorder);
// xml_appendTextNode($objXmlDom, $objDocNode, "sortorder", $sortorder);
if($arr[0] == "price") $type = 'number';
else $type = 'text';
$xml->addChild( "sorttype", $type);
// xml_appendTextNode($objXmlDom, $objDocNode, "sorttype", $type);
}
$sql = mysql_query("select * from items") or die(mysql_error());
while($row=mysql_fetch_object($sql))
{
$item = $xml->addChild('item');
$item->addAttribute('id', $row->id);
$item->addChild('name', $row->name);
$item->addChild('qty', $row->qty);
$item->addChild('price', $row->price);
}
Header('Content-type: text/xml');
print($xml->asXML());
?>
xslt file:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="sortby">
<xsl:choose>
<xsl:when test="sortby != ''">
<xsl:value-of select="items/sortby" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'price'" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="sorttype">
<xsl:choose>
<xsl:when test="sorttype != ''">
<xsl:value-of select="items/sorttype" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'text'" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="sortorder">
<xsl:choose>
<xsl:when test="sortorder != ''">
<xsl:value-of select="items/sortorder" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'ascending'" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:template match="/">
<html>
<body>
<h2>Item List</h2>
<div style="margin:20px;">
<label>Sort by: | <xsl:value-of select="items/sortby" /> | <xsl:value-of select="items/sorttype" /> | <xsl:value-of select="items/sortorder" /> </label>
<form id="sortform" method="post">
<select name="sort_by" onchange="javascript:document.getElementById('sortform').submit();">
<option> Select </option>
<option value="price_asc">Price ASC</option>
<option value="price_desc">Price DESC</option>
<option value="name_asc">Name ASC</option>
<option value="name_desc">Name DESC</option>
</select>
</form>
</div>
<table border="1">
<tr bgcolor="#9acd32">
<th>Item</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
<xsl:for-each select="items/item">
<xsl:sort data-type="{$sorttype}" select="*[name()=$sortby]" order="{$sortorder}" />
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="qty"/></td>
<td><xsl:value-of select="qty * price"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I think the problem you are having is with the setting of your three variables at the start of your XSLT
<xsl:variable name="sortby">
<xsl:choose>
<xsl:when test="sortby != ''">
<xsl:value-of select="items/sortby" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'price'" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
The condition for the xsl:when is not correct. It is looking for a sortby element under the document node, which doesn't exist, as the root element is actually items.
It should be the following:
<xsl:when test="items/sortby != ''">
Similarly for the other two variables.
As an aside, it looks like you are writing XML with an xsl:stylesheet processing instruction to do the transformation on the client. If you are PHP you should perhaps doing the transformation of the XML on the server, then just writing out the HTML result. That way you could get PHP to pass in the sort values as parameters, rather than appending them to the XML.
It's not possible to reproduce the problem using your code. The one thing that I see is that you are trying to sort by:
select="#*[name()=$sortby]"
but your product nodes have no attributes. Perhaps you mean to sort by:
select="*[name()=$sortby]"
?

SharePoint 2013 Blog: sort posts by authors

I'm trying to make a custom filter which sorts on authors (users) in the SharePoint 2013 blog. I'm working with XSL dataview and it's exported to a web part. I have a column called Author which gets the information from Created By. When I click on a user in the web part it shows all posts instead of the selected author. The URL is mysite/default.aspx?Author=FirstName LastName".
Code (default.aspx):
<xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">
<xsl:call-template name="dvt_1"/>
</xsl:template>
<xsl:template name="dvt_1">
<xsl:variable name="dvt_StyleName">RepForm3</xsl:variable>
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[not(#Author.title=preceding-sibling::Row/#Author.title)]" />
<xsl:call-template name="dvt_1.header">
<xsl:with-param name="Rows" select="$Rows" />
</xsl:call-template>
<div class="blogRefineByAuthorContainer">
<xsl:call-template name="dvt_1.body">
<xsl:with-param name="Rows" select="$Rows"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="dvt_1.header">
<xsl:param name="Rows" />
<div class="blogRefineByAuthorEveryAuthor">Everyone</div>
</xsl:template>
<xsl:template name="dvt_1.body">
<xsl:param name="Rows"/>
<xsl:for-each select="$Rows">
<xsl:call-template name="dvt_1.rowview" />
</xsl:for-each>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<div class="blogRefineByAuthorAuthorTitle">
<xsl:value-of select="#Author.title" />
</div>
</xsl:template>
Any ideas of what it could be? Between the first and last name there is a space in the URL, but I don't think it makes any sense. I have tried with %20 without any result.

umbraco xslt getMedia error

Searching for an error with GetMedia on Forum, I read that the variable i give the functions is not an integer.
Here is the error: System.OverflowException: Value was either too large or too small for an Int32.
I check my variable:
<xsl:value-of select="$currentPage/image" />
The output was:
1663
then i try this:
<xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/image, false())" />
It returns me the error I wrote you above. If i wrote 1663 instead of $currentPage/image it works but then it's hardcoded and it musn't be hardcoded.
Here my xslt
<xsl:template match="/">
<!-- start writing XSLT -->
<xsl:value-of select="$currentPage/image" />
<xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/image, false())" />
<div class="tfirst">
<p>
<!--xsl:if test="not($media/error)">
<img src="{$media/umbracoFile}" class="left timg" />
</xsl:if-->
<div class="ttext">
<h2><xsl:value-of select="umbraco.library:StripHtml($currentPage/title)" /></h2>
<xsl:value-of select="$currentPage/abstractText" disable-output-escaping="yes" />
</div>
</p>
</div>
<div class="ttext">
<xsl:if test="$currentPage/showMultipleColumns='1'">
<xsl:attribute name="class">showMultipleColumns</xsl:attribute>
</xsl:if>
<xsl:value-of select="$currentPage/bodyText" disable-output-escaping="yes" />
</div>
</xsl:template>
Thank you for your help.
Benjamin
Edit------------------
I've tried to add a if test but now it give me another error if i replace $currentPage/image by 1663 : System.Xml.Xsl.XslTransformException: To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set() function.
If i let the $currentPage/image I always have: System.OverflowException: Value was either too large or too small for an Int32.
Here is the xslt:
<xsl:variable name="atest" select="umbraco.library:GetMedia($currentPage/image, false())" />
<xsl:variable name="media">
<xsl:if test="$currentPage/image > 0">
<xsl:value-of select="$atest" />
</xsl:if>
</xsl:variable>
Edit2------------
Trying this below always getting the error: System.OverflowException: Value was either too large or too small for an Int32.
<xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/image, false())" />
<xsl:if test="$media">
<img src="{$media/umbracoFile}" class="left timg" />
</xsl:if>
You need to check if your $currentPage/image is > 0 before you call the umbraco.Library:GetMedia() function. I can't remember why it was like that, but I've encountered the same issue a few years ago and if I recall it correctly, there was a reason for doing so.
try this:
<xsl:variable name="mediaId" select="$currentPage/image)" />
<xsl:if test="$mediaId > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($mediaId, 0)" />
</xsl:if>
EDIT:
I'm confused with the check you need to add in the Umbraco Macro Editor with this.
Rendering an image should be as simple as this:
<xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/image, 0)" />
<xsl:if test="$media">
<xsl:variable name="url" select="$media/umbracoFile" />
<xsl:variable name="width" select="$media/umbracoWidth" />
<xsl:variable name="height" select="$media/umbracoHeight" />
<img src="{$url}" width="{$width}" height="{$height}" />
</xsl:if>
Thanks for your help.
Found my problem solution.
Because my image is not mandatory (yes something that i should tell before).
I just did that:
<xsl:if test="$currentPage/image > 0">
<xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/image, false())" />
<xsl:if test="not($media/error)">
<img src="{$media/umbracoFile}" class="left timg" />
</xsl:if>
</xsl:if>
Now it just works fine.
Thank you for your help.
Have a great day.
Benjamin

Resources