To assign dynamic URL's - xslt

I am new to XSLT Language, I am trying to write code that assigns dynamic URL's to Photo field in my list. My list contains FirstName, LastName and Photo fields of all employees and Photos are in a folder ("file://folder/subfolder/LastName, FirstName.jpg). Based on FirstName and LastName appropriate photo should be dynamically added to Photo Field.
Code I tried:
<xsl:template match="udt:Photo">
<xsl:for-each select="dnnGridItem">
<xsl:value-of select="udt:LastName" />
<xsl:value-of select="udt:FirstName" />
</xsl:for-each>
<img border="0" alt="delete">
<xsl:attribute name="src">
<xsl:text>file://folder/subfolder</xsl:text>
<xsl:value-of select="file://foilder/subfoilder/?{LastName}, {FirstName}.jpg" />
<xsl:text>.jpg</xsl:text>
</xsl:attribute>
</img>
</xsl:template>
Can any one help me with XSL code.

As you did not provide any input data I can suggest my example.
In my case required images are in path D:/images as below:
So to add images to HTML I am using next XSL file (photo.xsl) as below:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" />
<xsl:template match="/Photo">
<xsl:variable name="img.path" select="'file:///D:/images/'"/>
<html>
<body>
<xsl:for-each select="dnnGridItem">
<xsl:variable name="img.name" select="concat(LastName, ', ', FirstName)"/>
<h2>
<xsl:value-of select="$img.name"/>
</h2>
<img border="0" alt="delete">
<xsl:attribute name="src">
<xsl:value-of select="concat($img.path, $img.name, '.jpg')"/>
</xsl:attribute>
</img>
<br/>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Then to take LastName and FirstName dynamically add <?xml-stylesheet type="text/xsl" href="photo.xsl"?> to input XML file (input.xml) as below:
<?xml-stylesheet type="text/xsl" href="photo.xsl"?>
<Photo>
<dnnGridItem>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</dnnGridItem>
<dnnGridItem>
<FirstName>Kate</FirstName>
<LastName>Johnson</LastName>
</dnnGridItem>
</Photo>
Result:
Transformed result:
<html>
<body>
<h2>Smith, John</h2>
<img border="0" alt="delete" src="file:///D:/images/Smith, John.jpg"><br>
<h2>Johnson, Kate</h2>
<img border="0" alt="delete" src="file:///D:/images/Johnson, Kate.jpg"><br>
</body>
</html>
Result when open XML(input.xml) file in browser:
NOTE! input.xml - in same folder with photo.xsl.
Hope it will help with your case.

Related

xslt fields grouped by their type

I have some data that i put in (image, title, text). I ahve 3 different elements in my xslt for each of them:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:udt="DotNetNuke/UserDefinedTable" exclude-result-prefixes="udt">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<!--
This prefix is used to generate module specific query strings
Each querystring or form value that starts with udt_{ModuleId}_param
will be added as parameter starting with param
-->
<xsl:variable name="prefix_param">udt_<xsl:value-of select="//udt:Context/udt:ModuleId" />_param</xsl:variable>
<xsl:template match="udt:Data" mode="list">
<xsl:value-of select="udt:Image" disable-output-escaping="yes" />
<xsl:value-of select="udt:Title" disable-output-escaping="yes" />
<xsl:value-of select="udt:Text" disable-output-escaping="yes" />
</xsl:template>
<xsl:template match="/udt:UserDefinedTable">
<xsl:variable name="currentData" select="udt:Data" />
<xsl:if test="$currentData">
<xsl:apply-templates select="$currentData" mode="list">
</xsl:apply-templates>
</xsl:if>
</xsl:template>
<xsl:template name="EditLink">
<xsl:if test="udt:EditLink">
<a href="{udt:EditLink}">
<img border="0" alt="edit" src="{//udt:Context/udt:ApplicationPath}/images/edit.gif" />
</a>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I want to fill these elements each into its own div group, so my end result would be something like this:
<div id="images">
<!--all images here-->
</div>
<div id="title">
<!--all titles here-->
</div>
<div id="text">
<!--all texts here-->
</div>
Can this be achieved by any kind of grouping or whats the right aproach?
The concept to use xsl:value-of for your 3 element types is wrong,
as this instruction copies only the content of these elements,
without XML markup.
Assuming that the only goal is to reorder (group) your elements,
and they are direct descendants of the current element (udt:Data),
the task can be done the following way:
<xsl:template match="udt:Data">
<xsl:copy>
<div id="images">
<xsl:copy-of select="udt:Image"/>
</div>
<div id="title">
<xsl:copy-of select="udt:Title"/>
</div>
<div id="text">
<xsl:copy-of select="udt:Text"/>
</div>
</xsl:copy>
</xsl:template>
Of course, this is only a template, not the whole script.
Note that e.g. if these elements were located also at "deeper" descendant levels,
all the above XPath expressions should be prececed with descendant::.
And remember about including in your script all namespaces, the script refers to.
They should be declared in stylesheet tag.

cdata-section-elements not working for dynamically created element

I am trying to define some dynamically created elements as cdata sections, but it's not working for some reason:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes" method="xml"
cdata-section-elements="DESCRIPTION2"
/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/RSS/ITEM/TEST">
<DESCRIPTION2>
<div class="container">
<xsl:if test="NAME != ''">
<div class="test">
<xsl:value-of select="NAME"/>
</div>
</xsl:if>
</div>
</DESCRIPTION2>
</xsl:template>
</xsl:stylesheet>
Test XML:
<?xml version="1.0" encoding="UTF-8"?>
<RSS>
<ITEM>
<CODE>41,000</CODE>
<TEST>
<NAME><p>HTML code</p></NAME>
</TEST>
</ITEM>
</RSS>
Live test.
Sure I can add manually (<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>), but I would like to know why it's not working If I define it as cdata-section-elements.
CDATA serialization happens for text nodes inside of the nominated elements, if you put in elements there it doesn't happen. Note that, assuming an XSLT 3 processor with XPath 3.1 support, you can use the serialize function to serialize the content you build as html and then output it as a text node:
<xsl:template match="/RSS/ITEM/TEST">
<xsl:variable name="html">
<div class="container">
<xsl:if test="NAME != ''">
<div class="test">
<xsl:value-of select="NAME"/>
</div>
</xsl:if>
</div>
</xsl:variable>
<DESCRIPTION2>
<xsl:value-of select="serialize($html, map { 'method' : 'html' })"/>
</DESCRIPTION2>
</xsl:template>
http://xsltfiddle.liberty-development.net/948Fn5i/1 then gives the result as a CDATA section
<DESCRIPTION2><![CDATA[<div class="container">
<div class="test">Peter</div>
</div>]]></DESCRIPTION2>
Your content is well-formed XHTML, so it doesn't need to apply CDATA when serializing the content.
If you escaped the markup and constructed a string, it would serialize as CDATA:
<xsl:template match="/RSS/ITEM/TEST">
<DESCRIPTION2>
<div class="container">
<xsl:if test="NAME != ''">
<div class="test">
<xsl:value-of select="NAME"/>
</div>
</xsl:if>
</div>
</DESCRIPTION2>
</xsl:template>
Produces:
<DESCRIPTION2><![CDATA[
<div class="container">
<div class="test">
Peter
</div>
</div>
]]></DESCRIPTION2>
But why would you want to generate a string when you could have well-formed markup? It makes it a pain for everyone downstream.

XSLT Grouping for HTML

I have data for images like this:
<data>
<image>
<type>preview</type>
<pageNr>1</pageNr>
<url>5981-211.png</url>
</image>
<image>
<type>thumbnail</type>
<pageNr>1</pageNr>
<url>5549a_aldj_thumb.png</url>
</image>
<image>
<type>big thumb</type>
<url>47697-4921.png</url>
</image>
<image>
<type>preview</type>
<pageNr>2</pageNr>
<url>491-d91.png</url>
</image>
<image>
<type>thumbnail</type>
<pageNr>2</pageNr>
<url>491-d91_thumb.png</url>
</image>
</data>
And I want to create the following HTML output:
<a href="5981-211.png" title="1">
<img src="5549a_aldj_thumb.png" />
</a>
<a href="491-d91.png" title="2">
<img src="491-d91_thumb.png" />
</a>
For every preview there is a thumbnail with the same pageNr.
How can I group the data and nest the <img> into the <a> tag?
This can be achieved with the use of a key to lookup the "thumbnail" images
<xsl:key name="thumb" match="image[type='thumbnail']" use="pageNr" />
You would start off by selecting the "preview" elements
<xsl:apply-templates select="image[type='preview']"/>
And in the template that matches this, you would create the a tag, and then select the child "thumbnail" elements using the key
<a href="{url}" title="{pageNr}">
<xsl:apply-templates select="key('thumb', pageNr)" />
</a>
And in the template that matches the thumbnails, you would create the img tag like so:
<img src="{url}" />
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:key name="thumb" match="image[type='thumbnail']" use="pageNr" />
<xsl:template match="/data">
<body>
<xsl:apply-templates select="image[type='preview']"/>
</body>
</xsl:template>
<xsl:template match="image[type='preview']">
<a href="{url}" title="{pageNr}">
<xsl:apply-templates select="key('thumb', pageNr)" />
</a>
</xsl:template>
<xsl:template match="image[type='thumbnail']">
<img src="{url}" />
</xsl:template>
</xsl:stylesheet>

XSLT Parsing error when using Umbraco GetMedia

I am trying to retrieve the url to an image using the GetMedia mediapicker.
The code below works fine:
<xsl:for-each select="umbraco.library:GetXmlNodeById(1123)/* [#isDoc]">
<article>
<img width="1822" height="600">
<xsl:attribute name="src">
<xsl:value-of select="umbraco.library:GetMedia(1139, 0)/umbracoFile" />
</xsl:attribute>
</img>
<div class="contents">
<h1>
<xsl:value-of select="bannerHeading1"/>
</h1>
</div>
</article>
</xsl:for-each>
However, if I replace the key line with this:
<xsl:value-of select="umbraco.library:GetMedia(bannerImage, 0)/umbracoFile" />
I get a parsing error with the exception being an OverflowException (Value was either too large or too small for an Int32), which suggests that it's not the 1139 that is being passed in.
Is there a way I can pass in the property I want? The value of "bannerImage" is 1139 as I want it to be?
Thanks for any help.
Further: This is the XML structure being returned by GetXMLNodeById:
<?xml version="1.0" encoding="utf-8" ?>
<HomepageBanner id="1141" parentID="1123" level="3" writerID="0" creatorID="0" nodeType="1124" template="1125" sortOrder="0" createDate="2013-08-12T15:53:48" updateDate="2013-08-12T15:54:18" nodeName="Members" urlName="members" writerName="admin" creatorName="admin" path="-1,1065,1123,1141" isDoc="">
<bannerImage>1139</bannerImage>
<bannerHeading1>Members Area</bannerHeading1>
<bannerHeading2>..the place for all your needs</bannerHeading2>
</HomepageBanner>
For anyone else trying to get an image from an item in a content folder, this is how I got it to work:
<xsl:for-each select="umbraco.library:GetXmlNodeById(1123)/* [#isDoc]">
<article>
<!-- Store the ID -->
<xsl:variable name="mediaId" select="bannerImage" />
<!-- Check the ID is numeric -->
<xsl:if test="number($mediaId) > 0">
<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, false())" />
<xsl:if test="string-length($mediaNode/umbracoFile) > 0">
<img src="{$mediaNode/umbracoFile}" width="1822" height="600" />
<div class="contents">
<h1>
<xsl:value-of select="bannerHeading1"/>
</h1>
</div>
</xsl:if>
</xsl:if>
</article>
</xsl:for-each>
You first need to check that the value is numeric and then, the bit that was failing me, you need to add the "/umbracoFile" part to your media node variable.
Thanks to the contributors who helped me in the right direction.

HTML entities do not render correctly in browser after XSLT transform

I have the following XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<contactInfo>
<id>12319221</id>
<name>Jerry P</name>
<market>
<name>Test</name>
<phone>800.555.1010</phone>
</market>
<agent>
<name>Test User</name>
<email>testuser#email.com</email>
</agent>
<summary>&#8220;Jerry just gets it!&#8221;</summary>
</contactInfo>
</example>
I am encoding special characters as html entities when I save this xml document, hence how the smart quotes are encoded as “ and &#8221.
And I use an XSL, via Java/Xalan, to transform the xml document to html:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="wsHost"></xsl:param>
<xsl:param name="serverId"></xsl:param>
<xsl:template match="/showcase">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example</title>
</head>
<body>
<div id="profile">
<xsl:apply-templates/>
</div>
</body>
</html>
</xsl:template>
<!-- Contact Info section -->
<xsl:template match="/example/contactInfo">
<span class="sectionTitle">Contact Info:</span>
<div id="contactInfo">
<xsl:if test="name">
<strong>Candidate Name:</strong> <xsl:value-of disable-output-escaping="yes" select="name" /><br />
</xsl:if>
<xsl:if test="id">
<strong>Candidate ID:</strong> <xsl:value-of disable-output-escaping="yes" select="id" /><br />
</xsl:if>
<xsl:if test="market">
<xsl:if test="market/name">
<strong>Market Name:</strong> <xsl:value-of disable-output-escaping="yes" select="market/name" /><br />
</xsl:if>
<xsl:if test="market/phone">
<strong>Market Phone:</strong> <xsl:value-of disable-output-escaping="yes" select="market/phone" /><br />
</xsl:if>
</xsl:if>
<xsl:if test="agent">
<xsl:if test="agent/name">
<strong>Agent Name:</strong> <xsl:value-of disable-output-escaping="yes" select="agent/name" /><br />
</xsl:if>
<xsl:if test="agent/email">
<strong>Agent Email:</strong> <xsl:value-of disable-output-escaping="yes" select="agent/email" /><br />
</xsl:if>
</xsl:if>
<xsl:if test="summary">
<strong>Summary:</strong> <xsl:value-of disable-output-escaping="yes" select="summary" /><br />
</xsl:if>
</div>
<hr size="1" noshade="noshade" class="rule" />
</xsl:template>
</xsl:stylesheet>
The html that results from the transform is then written to the browser. Here is where I'm noticing a character encoding issue. The   (nbsp numeric value) show up as either black diamond question marks (firefox) or a box character (ie) and so do the entities that were previously encoded (“ / ”).
Also, maybe the biggest hint of all is that when transforming this xml file on a linux platform (then writing html to firefox) everything appears correctly. It's only when the transform is done from windows do the character encoding issues occur (in both firefox and ie).
Am I encoding the entities incorrectly or maybe not specify a character set somewhere?
You say you are using Java/Xalan. Are you prividing the output stream or stream writer? If so you need to explicitly set the encoding at that point:
... new OutputStreamWriter(stream,"UTF-8");
Just including the UTF8 headers does not actually cause the output file to be UTF8 encoded.
Well you havent set the encodeing in the HTML document for one. Dont know if thats the issue but that would be my first attempt to fix.
try adding:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
to your head.