I wonder two know that is it possible to bring two param inside template? and if so how? For example as this one:
<xsl:template name="formatDate">
<xsl:param name="timeParam"/>
<xsl:param name="withYear"/>
<xsl:variable name="dateParam" select="substring-before($timeParam,'T')"/>
<xsl:variable name="year" select="substring($dateParam,1,4)"/>
<xsl:variable name="month" select="substring($dateParam,6,2)"/>
<xsl:variable name="day" select="substring($dateParam,9,2)"/>
<xsl:if test="string-length($day) = 1">
<xsl:value-of select="'0'"/>
</xsl:if>
<xsl:value-of select="$day"/>
<xsl:value-of select="'.'"/>
<xsl:if test="string-length($month) = 1">
<xsl:value-of select="'0'"/>
</xsl:if>
<xsl:value-of select="$month"/>
<xsl:if test="string-length($withYear) = 1">
<xsl:value-of select="'.'"/>
<xsl:value-of select="'0'"/>
<xsl:with-param name="withYear" select="$year" />
</xsl:if>
</xsl:template>
and calling:
<xsl:call-template name="formatDate">
<xsl:with-param name="timeParam" select="attribute::time"/>
<xsl:with-param name="withYear" select="1"/>
</xsl:call-template>
<xsl:call-template name="formatDate">
<xsl:with-param name="timeParam" select="attribute::time"/>
</xsl:call-template>
As you see in some position I need year parameter and in others not.
Ps. The reason to use two parameter is that I do not want to duplicate the code.
I am not sure what exactly your question is. I am quite sure your named template needs to be changed, because you cannot have xsl:with-param as child of xsl:if.
I think that instead of:
<xsl:if test="string-length($withYear) = 1">
<xsl:value-of select="'.'"/>
<xsl:value-of select="'0'"/>
<xsl:with-param name="withYear" select="$year" />
</xsl:if>
you should have:
<xsl:if test="string-length($withYear) = 1">
<xsl:value-of select="'.'"/>
<xsl:value-of select="$year"/>
</xsl:if>
or simply:
<xsl:if test="$withYear">
<xsl:text>.</xsl:text>
<xsl:value-of select="$year"/>
</xsl:if>
Related
I'm new to XSL programming and facing an issue while trying to remove the HTML tags from the XML file.
My Input XML file is: Just adding the tag that I'm interested in
<Ingredients>
<p><b>INGREDIENTS:</b> Reduced Fat Cheese (84%) [Reduced Fat<strong>Milk</strong>, Salt, Starter Cultures, Enzyme (Animal Rennet, Lipase)],<strong>Milk</strong> Solids, Water, Emulsifying Salt (331), Salt, Acidity Regulator (330), Preservative (200), Natural Colours (100, 160b).</p>
</Ingredients>
My XSL file is:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.micros.com/creations/core/domain/dto/v1p0/full" xmlns:ns2="http://www.micros.com/creations/core/domain/dto/v1p0/simple" exclude-result-prefixes="ns1 ns1">
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="with"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$with"/>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="with" select="$with"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="strip-html-tags">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '<')">
<xsl:value-of select="substring-before($text, '<')"/>
<xsl:call-template name="strip-html-tags">
<xsl:with-param name="text" select="substring-after($text, '>')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$text"/>
<xsl:with-param name="replace" select="' '" />
<xsl:with-param name="with" select="''"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<ItemDetails>
<SourceSystem>
<xsl:text>Fusion</xsl:text>
</SourceSystem>
<ActionType>
<xsl:text>Create</xsl:text>
</ActionType>
<CreateDateTime>
<xsl:text>2021-11-10T08:00:00</xsl:text>
</CreateDateTime>
<Ingredients>
<xsl:call-template name="strip-html-tags">
<xsl:with-param name="text" select="ns1:productSpecificationFullDTO/ns1:specificationSectionDetail/ns1:specificationSectionFoodRecipeAndRawMaterialsSection/ns1:onPackIngredientsList"/>
<!--<xsl:with-param name="replace" select="' '"/>
<xsl:with-param name="with" select="''"/>-->
</xsl:call-template>
</Ingredients>
</ItemDetails>
</xsl:template>
</xsl:stylesheet>
Using the above XSL file I'm trying to remove the HTML tags and also trying to replace the special character like with empty. Hence I'm calling 2 templates.
<xsl:template name="strip-html-tags"> strips the other tags but not " "
So created a <xsl:template name="replace-string"> to replace " " with ''.
However this is not working. either of the templates works when invoked first.
If <xsl:template name="strip-html-tags"> is invoked first, it removes all the HTML tags except " "
If <xsl:template name="replace-string"> is invoked first, it replace the " " with '' but the other HTML tags are not removed.
I am calling these templates in the when clause.
How can this issue be solved? I need all the HTML tags to be removed. Is there a way to do it at single go or is it something that I'm missing?
If you want to use the output of one template as the input to the other template, then call the first template within the xsl:with-param instruction of the second template - for example:
<xsl:call-template name="replace-string">
<xsl:with-param name="text">
<xsl:call-template name="strip-html-tags">
<xsl:with-param name="text" select="Ingredients"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="replace" select="' '" />
<xsl:with-param name="with" select="''"/>
</xsl:call-template>
Simplified demo: https://xsltfiddle.liberty-development.net/eiorv1s
Ensure that you are scrubbing the value that is between the tags, not just selecting it. Instead of xsl:value-of, run it through the replace-string template.
Also, you may want to replace with a space ' ' instead of empty string. Otherwise, you will get ReducedFat instead of Reduced Fat
<xsl:when test="contains($text, '<')">
<!--<xsl:value-of select="substring-before($text, '<')"/>-->
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="substring-before($text, '<')"/>
<xsl:with-param name="replace" select="' '" />
<xsl:with-param name="with" select="' '"/>
</xsl:call-template>
<xsl:call-template name="strip-html-tags">
<xsl:with-param name="text" select="substring-after($text, '>')"/>
</xsl:call-template>
</xsl:when>
I have a string like below and trying to convert into json format:
Test "out" and \new
Expected output is
Test \"out\" and \new
I tried by calling templates for escapequote - working fine for escape quotes:
<xsl:template name="escapeQuote">
<xsl:param name="pText" select="concat(normalize-space(.), '')" />
<xsl:if test="string-length($pText) >0">
<xsl:value-of select="substring-before(concat($pText, '"'), '"')" />
<xsl:if test="contains($pText, '"')">
<xsl:text>\"</xsl:text>
<xsl:call-template name="escapeQuote">
<xsl:with-param name="pText" select="substring-after($pText, '"')" />
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
Template for escape backslash - working for only backslash:
<xsl:template name="jsonescape">
<xsl:param name="str" select="."/>
<xsl:choose>
<xsl:when test="contains($str, '\')">
<xsl:value-of select="concat(substring-before($str, '\'), '\\' )"/>
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="substring-after($str, '\')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
My question how to call both templates or merge, please help me
Here is an example of how you can combine the two template calls, so that the output from jsonescape is used as an input parameter to escapequote
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" />
<xsl:template match="input">
<xsl:call-template name="escapeQuote">
<xsl:with-param name="pText">
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="." />
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="escapeQuote">
<xsl:param name="pText" select="concat(normalize-space(.), '')" />
<xsl:if test="string-length($pText) >0">
<xsl:value-of select="substring-before(concat($pText, '"'), '"')" />
<xsl:if test="contains($pText, '"')">
<xsl:text>\"</xsl:text>
<xsl:call-template name="escapeQuote">
<xsl:with-param name="pText" select="substring-after($pText, '"')" />
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:template name="jsonescape">
<xsl:param name="str" select="."/>
<xsl:choose>
<xsl:when test="contains($str, '\')">
<xsl:value-of select="concat(substring-before($str, '\'), '\\' )"/>
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="substring-after($str, '\')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
So, given this an input:
<input>Test "out" and \new</input>
The following is output
Test \"out\" and \\new
Note that the order is important, because if you reversed the order of the template calls, the " would get converted to \" by the escapequote template, which would then get converted to \\" by the jsonescape template.
Alternatively, as both template do a similar thing, of putting a \ before specific characters, you could combine the two templates into one.
Try this XSLT too
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" />
<xsl:template match="input">
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="jsonescape">
<xsl:param name="str" select="."/>
<xsl:param name="escapeChars" select="'\"'" />
<xsl:variable name="first" select="substring(translate($str, translate($str, $escapeChars, ''), ''), 1, 1)" />
<xsl:choose>
<xsl:when test="$first">
<xsl:value-of select="concat(substring-before($str, $first), '\', $first)"/>
<xsl:call-template name="jsonescape">
<xsl:with-param name="str" select="substring-after($str, $first)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$str"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
There have been similar questions but none working with SharePoint and the XSL editor.
I have an RSS feed which is pulling in article titles, along with accompanying html tags as shown below:
<i>Wall Street Journal</i> Article on Competition in the Dental Industry
I would like to have those <i> (and any other HTML tags) be read as HTML, not text..i.e an end result of:
Wall Street Journal Article on Competition in the Dental Industry
I can read and semi-reverse engineer XML, but writing it is another story.
Any help will be greatly appreciated.
A sample of my code where I think the changes is needed, below:
<xsl:template name="RSSMainTemplate.body" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:param name="Rows"/>
<xsl:param name="RowCount"/>
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:variable name="RssFeedLink" select="$rss_WebPartID" />
<xsl:variable name="CurrentElement" select="concat($RssFeedLink,$CurPosition)" />
<xsl:if test="($CurPosition <= $rss_FeedLimit)">
<div class="item link-item" >
<a href="{concat("javascript:ToggleItemDescription('",$CurrentElement,"')")}" >
<xsl:value-of select="title"/>
</a>
<xsl:if test="$rss_ExpandFeed = true()">
<xsl:call-template name="RSSMainTemplate.description">
<xsl:with-param name="DescriptionStyle" select="string('display:block;')"/>
<xsl:with-param name="CurrentElement" select="$CurrentElement"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="$rss_ExpandFeed = false()">
<xsl:call-template name="RSSMainTemplate.description">
<xsl:with-param name="DescriptionStyle" select="string('display:none;')"/>
<xsl:with-param name="CurrentElement" select="$CurrentElement"/>
</xsl:call-template>
</xsl:if>
</div>
</xsl:if>
</xsl:for-each>
</xsl:template>
Figured it out.
The key to this issue is the disable-output-escaping attribute. I was correct about the location of the issue. Below is my adjusted code. Notice lines 10-15
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:param name="Rows"/>
<xsl:param name="RowCount"/>
<xsl:for-each select="$Rows">
<xsl:variable name="CurPosition" select="position()" />
<xsl:variable name="RssFeedLink" select="$rss_WebPartID" />
<xsl:variable name="CurrentElement" select="concat($RssFeedLink,$CurPosition)" />
<xsl:if test="($CurPosition <= $rss_FeedLimit)">
<div class="item link-item" >
<a href="{concat("javascript:ToggleItemDescription('",$CurrentElement,"')")}" >
<xsl:variable name="SafeHtml">
<xsl:call-template name="GetSafeHtml">
<xsl:with-param name="Html" select="title"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$SafeHtml" disable-output-escaping="yes"/>
</a>
<xsl:if test="$rss_ExpandFeed = true()">
<xsl:call-template name="RSSMainTemplate.description">
<xsl:with-param name="DescriptionStyle" select="string('display:block;')"/>
<xsl:with-param name="CurrentElement" select="$CurrentElement"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="$rss_ExpandFeed = false()">
<xsl:call-template name="RSSMainTemplate.description">
<xsl:with-param name="DescriptionStyle" select="string('display:none;')"/>
<xsl:with-param name="CurrentElement" select="$CurrentElement"/>
</xsl:call-template>
</xsl:if>
</div>
</xsl:if>
</xsl:for-each>
<div class="description">
<h4 class="ms-rteElement-H4B">
<span class="ms-rteStyle-Emphasis">
<br></br>View More Articles <img alt="more-icon-1.png" src="/BHiveImageGallery/Stock-Images/more-icon-1.png"/>
</span>
<span class="ms-rteStyle-Emphasis"> </span>
</h4>
</div>
My full code is too long and formatted too uniquely to get it to display as I want in the window. It is 3/20/2015 right now, if you message me within the next 5 years i'll be able to send you the code, beyond that, no guarantees haha.
Generally though I used the SharePoint 2013 standard RSS viewer webpart code, and only modified the piece above
I have been scouring the web for something like this and being a lazy programmer, before I attempt to do so myself, I thought I would ask here.
What I would like is a method to take any xml with node names following a convention (like cakephp or ruby) and then for that data to be presented in a ready to print format.
ie:
<xml>
<home_address>The Street</home_address>
</xml>
to:
<tr><td>Home Address</td><td>The Street</td></tr>
etc. with children having separate tables.
It seems pretty straightforward and something that would have been desired many times before. I found one useful discussion, but with no conclusion.
http://www.daniweb.com/software-development/xml-xslt-and-xpath/threads/363621/xml-to-html-using-xslt-without-hardcoding-node-names-in-xslt
Have I missed something here? Is there a simple generic xslt/css method for doing this? Or is this work being repeated hundreds of times a day in cubicles around the world?
Thanks in advance,
F
use the following XSL stylesheet. I have tested it and it works.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:template match="/">
<xsl:for-each select="*">
<xsl:for-each select="*">
<tr>
<xsl:variable name="NodeNameClearText">
<xsl:call-template name="repalceNodeName">
<xsl:with-param name="value" select="local-name(.)"/>
</xsl:call-template>
</xsl:variable>
<td>
<xsl:value-of select="$NodeNameClearText" />
</td>
<td>
<xsl:value-of select="." />
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="repalceNodeName">
<xsl:param name="value"/>
<xsl:variable name="valueWithoutUnderscores">
<xsl:value-of select="translate($value, '_',' ')"/>
</xsl:variable>
<xsl:call-template name="caseLowerAcceptFirstWord">
<xsl:with-param name="data" select="$valueWithoutUnderscores"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="caseDown">
<xsl:param name="data"/>
<xsl:if test="$data">
<xsl:choose>
<xsl:when test="starts-with($data,' ')">
<xsl:text> </xsl:text>
<xsl:call-template name="caseLowerAcceptFirstWord">
<xsl:with-param name="data" select="normalize-space(substring($data,2))"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(substring($data,1,1),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/>
<!-- put all the chars you want to change
into the last two strings -->
<xsl:call-template name="caseDown">
<xsl:with-param name="data" select="substring($data,2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template name="caseUP">
<xsl:param name="data"/>
<xsl:if test="$data">
<xsl:choose>
<xsl:when test="starts-with($data,' ')">
<xsl:text> </xsl:text>
<xsl:call-template name="caseLowerAcceptFirstWord">
<xsl:with-param name="data" select="substring($data,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(substring($data,1,1),
'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
<!-- put all the chars you want to change
into the last two strings -->
<xsl:call-template name="caseDown">
<xsl:with-param name="data" select="substring($data,2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template name="caseLowerAcceptFirstWord">
<xsl:param name="data"/>
<xsl:variable name="upperData">
<xsl:call-template name="caseUP">
<xsl:with-param name="data" select="$data"/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$upperData">
<xsl:value-of select="substring($upperData,1,1)"/>
<xsl:call-template name="caseDown">
<xsl:with-param name="data" select="substring($data,2)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
A little more info on what I tested. The following XML:
<xml>
<home_address>The Street</home_address>
<po_box>474</po_box>
</xml>
Was output to
<tr><td>Home Address</td><td>The Street</td></tr>
<tr><td>Po Box</td><td>474</td></tr>
If thats not what you wanted your question is to vague
I have this xslt which is working:
<xsl:when test="area_of_expertise">
<div>
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
but what i need is along the lines of:
<xsl:when test="area_of_expertise">
<div id="<xsl:value-of select="area_of_expertise"/>">
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
However the second example has errors.. does anyone know why?
Btw Is there a way we can transform the node's name area_of_expertise into areaOfExperiseLabel and insert that as the id? the output that i really need is this:
<div id="areaOfExpertiseLabel">
asasdasdasd
</div>
The reason it errors out is because it's no longer valid XML.
To do what you're trying to do:
<xsl:when test="title">
<div id="{title}">
<xsl:value-of select="title"/>
</div>
</xsl:when>
You can put any sort of selector inside of the {} tags, or even reference variables if you have something complex.
<xsl:variable name="some_complex_variable">
<xsl:value-of select="title"/>
</xsl:variable>
<xsl:when test="title">
<div id="{$some_complex_variable}">
<xsl:value-of select="title"/>
</div>
</xsl:when>
A 3rd, long-winded way of doing it is to dynamically attach the attribute with xsl:attribute:
<xsl:when test="title">
<div>
<xsl:attribute name="id" select="title"/>
</div>
</xsl:when>
For 2nd part try using this template:
<xsl:template name="parse">
<xsl:param name="input"/>
<xsl:param name="position"/>
<xsl:if test="$position <= string-length($input)">
<xsl:choose>
<xsl:when test="substring($input, $position, 1) = '_'">
<xsl:value-of select="translate(substring($input, $position + 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
<xsl:call-template name="parse">
<xsl:with-param name="input" select="$input"/>
<xsl:with-param name="position" select="$position + 2"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($input, $position, 1)"/>
<xsl:call-template name="parse">
<xsl:with-param name="input" select="$input"/>
<xsl:with-param name="position" select="$position + 1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
Usage:
<xsl:call-template name="parse">
<xsl:with-param name="input" select="'area_of_expertise'"/>
<xsl:with-param name="position" select="1"/>
</xsl:call-template>
For the second part, converting from underscores to camel case, you may want to look at String Processing in the XSLT Standard Library. With str:subst() to split at underscores, str:to-camelcase() to change letter case suitably, and concat() to add the "Label" suffix, you should be set.
For the 1st part you could use:
<xsl:when test="area_of_expertise">
<div>
<xsl:attribute name="id">
<xsl:value-of select="area_of_expertise"/>
</xsl:attribute>
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
It might be a silly answer, but it seems that you need this simple trace:
<xsl:when test="area_of_expertise">
<div id="areaOfExperiseLabel">
<xsl:value-of select="area_of_expertise"/>
</div>
</xsl:when>
Otherwise, why are you intersted in <xsl:value-of select="area_of_expertise"/> for #id if you then need another string?