Converting to img tag in xlst - xslt

This is my xml file:
<xml>
<figure>abstract.png</figure>
</xml>
This is my xslt code:
<xsl:template match="figure">
<img src="{.}" alt=""/>
<xsl:value-of select="."/>
</xsl:template>
But it gives this:
<img src="abstract.png" alt=""/>abstract.png
instead of just:
<img src="abstract.png" alt=""/>
How to remove the last abstract.png?

The trailing string abstract.png is produced by your instruction:
<xsl:value-of select="."/>
If you remove it, you will get the expected result:
https://xsltfiddle.liberty-development.net/aiyndL

Related

To assign dynamic URL's

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.

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.

getting the value of the previous elements in other template in xslt

Source:
<Data>
<AB>
<choice>Disclose</choice>
<image>
<img alt="No Image" xlink:href="abcd:202-11587" xmlns="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:title="Image" />
</image>
<link>abcd</link>
</AB>
<AB>
<choice>All</choice>
<image>
<img alt="No Image" xlink:href="abcd:202-2202" xmlns="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:title="Image" />
</image>
<link>all</link>
</AB>
</Data>
XSLT
<xsl:template match="Data">
<xsl:for-each select="AB">
<xsl:variable name="temp" select="choice"/>
<xsl:choose>
<xsl:when test="$temp='Disclose'">
<xsl:apply-templates select="image/node()"/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="simple:image/xhtml:img">
<!-- I want to get the the name of the "choice" here-->
<!-- some other process-->
<!-- how to access the value of the <choice> element of that section-->
<!-- how to access <link> element of that section-->
</xsl:template>
Can any one help how to do it.
Firstly, as this may just be an oversight with your code sample, you have specified namespaces in your matching template
<xsl:template match="simple:image/xhtml:img">
However, there are no references to the "simple" namespace in your sample XML, so in this case it should just be the following
<xsl:template match="image/xhtml:img">
But in answer to you question, to get the choice element, because you currently posisioned on the img element, you can search back up the hierarchy, like so
<xsl:value-of select="../../choice" />
The '..' represents the parent element. So, you are going back up to the AB element, and getting its child choice element.
And similarly for the link element
<xsl:value-of select="../../link" />
Note, it doesn't have to be xsl:value-of here, if there were multiple link elements, you could use xsl:apply-templates
<xsl:apply-templates select="../../link" />
And, if you required only link elements that occurred after the parent image element, you could do something like this
<xsl:apply-templates select="../following-sibling::link" />

XSLT transform of XML document to XHTML document

Here's my template:
<xsl:template name="rec">
<xsl:for-each select="*">
<div class="{local-name()}">
<xsl:for-each select="#*">
<xsl:attribute name="data-{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:value-of select="text()" />
<xsl:call-template name="rec" />
</div>
</xsl:for-each>
</xsl:template>
Given a document like so:
<test>
<item value="1">Item 1 Text</item>
<item value="2">Item 2 Text</item>
</test>
The above transform will turn it into:
<div class="test">
<div class="item" data-value="1">Item 1 Text</div>
<div class="item" data-value="2">Item 2 Text</div>
</div>
The problem I'm having, is that this transform doesn't respect text nodes properly, and I don't have enough background with XSLT to figure out how to fix it. Here's the problem: given xml like so:
<para>This is a <emphasis>paragraph</emphasis> people!</para>
I would like to see the following output:
<div class="para">This is a <div class="emphasis">paragraph</div> people!</div>
The problem is that I'm not getting this - I'm getting this:
<div class="para">This is a <div class="emphasis">paragraph</div></div>
Notice the missing 'people!' text node. How can I fix my XSLT above to provide me with the output I need?
One problem is that
<xsl:value-of select="text()" />
just selects the value of the first child text node, and outputs it.
The easiest way to do this right is probably to use <xsl:apply-templates> instead of <xsl:call-template>.
Then instead of
<xsl:for-each select="*">
and
<xsl:value-of select="text()" />
you can use
<xsl:apply-templates />
which will apply the appropriate template to each child element and text node, in order, not skipping any.
Here is a complete implementation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="*">
<div class="{local-name()}">
<xsl:for-each select="#*">
<xsl:attribute name="data-{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates />
</div>
</xsl:template>
</xsl:stylesheet>
Note the <xsl:apply-templates/>, which operates on all children of the context node, including text nodes, by default in absence of an explicit select attribute.
A default template is used for text nodes. This template simply copies them to the output.
Sample input:
<test>
<item value="1">Item 1 Text</item>
<item value="2">Item 2 Text</item>
<para>This is a <emphasis>paragraph</emphasis> people!</para>
</test>
produces the desired output:
<div class="test">
<div class="item" data-value="1">Item 1 Text</div>
<div class="item" data-value="2">Item 2 Text</div>
<div class="para">This is a <div class="emphasis">paragraph</div> people!</div>
</div>

XSLT: Foreach iterates for each item, but displays the value of the first item?

I have a item list and for each item I want to make it an url.
List:
<root>
<tags>
<tag>open source</tag>
<tag>open</tag>
<tag>advertisement</tag>
<tag>ad</tag>
</tags>
</root>
XSLT:
<xsl:template match="*">
<div class="tags">
<xsl:for-each select="/post/tags/tag">
<a href="#">
<xsl:value-of select="//tag"/>
</a>
</xsl:for-each>
</div>
</xsl:template>
Output:
<div class="tags">
open source
open source
open source
open source
</div>
What am I doing wrong?
A more XSLT way of doing the correct thing is add a "tag" template and modify your original:
<xsl:template match="*">
<div class="tags">
<xsl:apply-templates select="tag" />
</div>
</xsl:template>
<xsl:template match="tag">
<a href="#">
<xsl:value-of select="."/>
</a>
</xsl:template>
What you are doing with the value-of expression is selecting all of the tag nodes in the xml document:
<xsl:value-of select="//tag"/>
The effect of that is that only the first selected node will be used for the value.
You can use the following instead:
<xsl:value-of select="."/>
Where select="." will select the current node from the for-each.