left trim white space xslt 1.0 - xslt

I am creating a left trim template and I have this below template:
<xsl:template name="str:left-trim">
<xsl:param name="string" select="''"/>
<xsl:variable name="tmp" select="substring($string, 1, 1)"/>
<xsl:if test="$tmp = ' '">
<xsl:variable name="tmp2" select="substring-after($string, $tmp)"/>
<xsl:choose>
<xsl:when test="$tmp2 != ''">
<xsl:call-template name="str:left-trim">
<xsl:with-param name="string" select="$tmp2"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tmp2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test="$tmp != ' '">
<xsl:value-of select="$string"/>
</xsl:if>
</xsl:template>
if I pass an argument like this:
<xsl:variable name="str-test2">this is a america</xsl:variable>
then my template will work just fine but if I pass an argument like this below then, my template will fail. I think there is something wrong with the break(newline)
<xsl:variable name="str-test2">
this is a america
</xsl:variable>
do you have any suggestion?

This works for me. Note I didn't use the str: namespace plus I'm checking for leading newlines.
<xsl:template name="left-trim">
<xsl:param name="string" select="''"/>
<xsl:variable name="tmp" select="substring($string, 1, 1)"/>
<xsl:choose>
<xsl:when test="$tmp = ' ' or $tmp = '
'">
<xsl:call-template name="left-trim">
<xsl:with-param name="string" select="substring-after($string, $tmp)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
HTH, Axel.

Here's a solution to left-trim a string in XSLT 1.0 without using a recursive template:
<xsl:value-of select="substring($str-test2, string-length(substring-before($str-test2, substring(normalize-space($str-test2), 1, 1))) + 1)"/>

Related

XSLT split address on line break

I have one XML with an address like this:
<ADDRESS>SHIPPING ADDRESS 1
SHIPPING ADDRESS 2
SHIPPING ADDRESS 3</ADDRESS>
and I need to convert it to:
<ADDRESS1>SHIPPING ADDRESS 1</ADDRESS1>
<ADDRESS2>SHIPPING ADDRESS 2</ADDRESS2>
(ignore third line).
NOTE: I am using XSLT 1.0
If you only want the first two lines, you could do:
<xsl:template match="ADDRESS">
<ADDRESS1>
<xsl:value-of select="substring-before(., '
')" />
</ADDRESS1>
<ADDRESS2>
<xsl:value-of select="substring-before(substring-after(., '
'), '
')" />
</ADDRESS2>
</xsl:template>
This assumes there are at least three lines. Otherwise it gets a bit more complicated. For example, you could use:
<xsl:template match="ADDRESS">
<xsl:variable name="address" select="concat(., '
')" />
<ADDRESS1>
<xsl:value-of select="substring-before($address, '
')" />
</ADDRESS1>
<ADDRESS2>
<xsl:value-of select="substring-before(substring-after($address, '
'), '
')" />
</ADDRESS2>
</xsl:template>
to create two address lines no matter how many lines the source address has.
Here's another answer that works for any number of lines:
<xsl:template match="ADDRESS">
<xsl:call-template name="splitAddress">
<xsl:with-param name="string" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="splitAddress">
<xsl:param name="string"/>
<xsl:param name="AddrNo" select="1"/>
<xsl:choose>
<xsl:when test="$AddrNo = 2">
<xsl:element name="ADDRESS{$AddrNo}">
<xsl:value-of select="substring-before($string, '
')"/>
</xsl:element>
</xsl:when>
<xsl:when test="contains($string, '
')">
<xsl:element name="ADDRESS{$AddrNo}">
<xsl:value-of select="substring-before($string, '
')"/>
</xsl:element>
<xsl:call-template name="splitAddress">
<xsl:with-param name="string" select="substring-after($string, '
')"/>
<xsl:with-param name="AddrNo" select="$AddrNo + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:element name="ADDRESS{$AddrNo}">
<xsl:value-of select="$string"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
--Edit--
I missed the requirement to stop after the second address line. I've inserted the xsl:when above to end the processing as required: the condition here can be edited as required.

Adjust Word 2013 Bibliography style to display an APA citation as (firstname lastname, year) based on the source locale

My thesis uses an APA citation. However, with research documents that is written in Thai, an inline citation must be of the form (firstname lastname, year) rather than the APA (lastname, year). This should be possible with a custom Microsoft Word 2013 bibliography style which would require an adjustment to the APA.XSL file in C:\Program Files (x86)\Microsoft Office\Office14\Bibliography\Style to include an additional logic similar to the follow:
<xsl:choose>
<xsl:when test="b:LCID='1054'">
(Firstname Lastname, year)
</xsl:when>
<xsl:otherwise>
(Lastname, year)
</xsl:otherwise>
</xsl:choose>
I believe that the additional logic should be added in this section, and that it must involve an adjustment to xsl:template formatNameCore.
<xsl:variable name="author0">
</xsl:variable>
However, my mind is drawing a blank beyond that. I wonder if anyone could point me to a correct direction. Help is much appreciated.
Here's the current xsl file.
After some more searching (and reading), I have stumbled upon this post in which all the temp1_prop_APA__ are specified as included below:
templ_prop_APA_MainAuthors_FML = %L, %f %m
templ_prop_APA_MainAuthors_FM = %f %m
templ_prop_APA_MainAuthors_ML = %L, %m
templ_prop_APA_MainAuthors_FL = %L, %f
Having nothing to lose; hence, I tried. While I do not know how exactly these %L, %F, or %M and their lowercase counterparts have came to be (explanations would have been nice), the expressions do work. In turn, included below is the section of adjusted code. So far, it seems to work for the purpose.
<xsl:template name="templ_prop_APA_CitationLong_FML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %M %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L, %F %M'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationLong_FM" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %M'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%F %M'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationLong_ML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%M %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L, %M'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationLong_FL" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L, %F'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationShort_FML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %M %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationShort_FM" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %M'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%F'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationShort_ML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%M %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="templ_prop_APA_CitationShort_FL" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$_LCID='1054'">
<xsl:value-of select="'%F %L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'%L'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Note: A full file is included here.
It has something to do with these templates:
<xsl:template name="templ_prop_APA_CitationShort_FML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FML"/>
</xsl:template>
<!-- ... -->
<xsl:template name="templ_prop_APA_CitationShort_FL" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FL"/>
</xsl:template>
Try:
<xsl:template name="templ_prop_APA_CitationShort_FML" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FM"/>
<xsl:text> </xsl:text>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FML"/>
</xsl:template>
<!-- ... -->
<xsl:template name="templ_prop_APA_CitationShort_FL" >
<xsl:param name="LCID" />
<xsl:variable name="_LCID">
<xsl:call-template name="localLCID">
<xsl:with-param name="LCID" select="$LCID"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FM"/>
<xsl:text> </xsl:text>
<xsl:value-of select="/*/b:Locals/b:Local[#LCID=$_LCID]/b:APA/b:CitationShort/b:FL"/>
</xsl:template>
I can't figure out where these values are getting populated, so this is the best I can do for now.
It seem safe to make this change here, instead of in the loop in <xsl:variable name="author0">...</xsl:variable>, as it's only ever called from there. This change won't affect your bibliography.
You may also have to modify the other temp1_prop_APA_*_* templates similarly.

Removing &#160 with XSLT

I hope someone can help me with this...
I am using SharePoint 2013 and trying to render a CQWP to show the latest blog posts. The problem I have is that when displaying the 'content' from the post I get '&#160' added and quotes are shown as '&quot'. I have managed to strip the HTML mark up but can't seem to get rid of these.
My code is as follows - any help would be much appreciated, thanks.
Generate Summary and Remove HTML
<!-- Generate Summary -->
<xsl:template name="GenerateSummary">
<xsl:param name="Content"/>
<xsl:param name="Length"/>
<xsl:param name="Suffix"/>
<xsl:variable name="cleanContent">
<xsl:call-template name="RemoveHtml">
<xsl:with-param name="String" select="$Content"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="SubstringBeforeLast">
<xsl:with-param name="String"
select="substring($cleanContent, 1, $Length)"/>
<xsl:with-param name="Char" select="' '"/>
</xsl:call-template>
<xsl:if test="string-length($cleanContent) > $Length">
<xsl:value-of select="$Suffix"
disable-output-escaping="yes"/>
</xsl:if>
</xsl:template>
<!-- RemoveHTML -->
<xsl:template name="RemoveHtml">
<xsl:param name="String"/>
<xsl:choose>
<xsl:when test="contains($String, '<')">
<xsl:value-of select="substring-before($String, '<')"/>
<xsl:call-template name="RemoveHtml">
<xsl:with-param name="String"
select="substring-after($String, '>')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$String"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="SubstringBeforeLast">
<xsl:param name="String" />
<xsl:param name="Char" />
<xsl:param name="subsequent"/>
<xsl:choose>
<xsl:when test="contains($String, $Char)">
<xsl:if test="$subsequent = 1">
<xsl:value-of select="$Char"/>
</xsl:if>
<xsl:value-of select="substring-before($String, $Char)"/>
<xsl:call-template name="SubstringBeforeLast">
<xsl:with-param name="String"
select="substring-after($String, $Char)" />
<xsl:with-param name="Char" select="$Char" />
<xsl:with-param name="subsequent" select="1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:if test="$subsequent != 1">
<xsl:value-of select="$String"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Calling it here
<div class="fcItemContent">
<xsl:call-template name="GenerateSummary">
<xsl:with-param name="Content" select="#content" />
<xsl:with-param name="Length" select="200" />
<xsl:with-param name="Suffix" select="'...'"/>
</xsl:call-template>
</div>
Use function of XSLT
normalize-space()
**<xsl:value-of select="normalize-space()"/>**
White space is normalized by stripping leading and trailing white space and replacing sequences of white space characters with a single space. If the argument is omitted, the string-value of the context node is normalized and returned.
referred Link :
Remove Space using XSLT

Count unique values in comma separated value in xslt 1.0

I have a node in an XML file:
<TEST_STRING>12,13,12,14</TEST_STRING>
I need to count how many unique numbers/values this string has. For example, in this case there are 2 unique values i.e. 13 and 14.
Honestly speaking i could not build anything yet. It seems it is difficult in XSLT 1.0 but my system only supports 1.0.
Is there any solution for it?
If your processor supports a node-set extension function (either exslt or the Microsoft msxsl one) then you can do it in two steps, first split the string and build an XML fragment with one element per value, then use normal XPath techniques to find the singletons.
Step one can be done with a tail-recursive template:
<xsl:template name="splitString">
<xsl:param name="str"/>
<xsl:choose>
<xsl:when test="contains($str, ',')">
<item><xsl:value-of select="substring-before($str, ',')"/></item>
<xsl:call-template name="splitString">
<xsl:with-param name="str" select="substring-after($str, ',')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<item><xsl:value-of select="$str"/></item>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
In the appropriate place you can call this as
<xsl:variable name="itemsRTF">
<xsl:call-template name="splitString">
<xsl:with-param name="str" select="TEST_STRING"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="items" select="exsl:node-set($itemsRTF)"/>
The items variable now contains a fragment of XML like
<item>12</item>
<item>13</item>
<item>12</item>
<item>14</item>
The next challenge is to find the singletons, which you can do with an expression like
$items/item[not(. = (preceding-sibling::item | following-sibling::item))]
(There are more efficient approaches using a key but for small numbers of items it's probably not worth the bother). So to count the singletons
<xsl:value-of select="count($items/item[not(. = (preceding-sibling::item | following-sibling::item))])"/>
It's possible without nodesets. It's not optimal, of course (hello, Shlemiel The Painter), but it's pretty easy - increment counter only if there is no given string ahead or behind.
Template
<xsl:template name="calcUnique">
<xsl:param name="str"/>
<xsl:param name="back"/>
<xsl:param name="count"/>
<xsl:if test="$str">
<xsl:choose>
<xsl:when test="contains($str, ',')">
<xsl:variable name="part" select="substring-before($str, ',')"/>
<xsl:call-template name="calcUnique">
<xsl:with-param name="str" select="substring-after($str, ',')"/>
<xsl:with-param name="back" select="concat($back, ',', $part)"/>
<xsl:with-param name="count">
<xsl:choose>
<xsl:when test="contains(concat($str, ','), concat(',', $part, ',')) or contains(concat($back, ','), concat(',', $part, ','))">
<xsl:value-of select="$count"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$count + 1"/></xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(concat($back, ','), concat(',', $str, ','))">
<xsl:value-of select="$count"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$count + 1"/></xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
Sample usage
<xsl:variable name="result">
<xsl:call-template name="calc">
<xsl:with-param name="str" select="TEST_STRING"/>
<xsl:with-param name="back" select="''"/>
<xsl:with-param name="count" select="0"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$result"/>

How do I preserve line feeds, tabs, and spaces in data while still wrapping text?

I had data in XML that had line feeds, spaces, and tabs that I wanted to preserve in the output HTML (so I couldn't use <p>) but I also wanted the lines to wrap when the side of the screen was reached (so I couldn't use <pre>).
Another way of putting this is that you want to turn all pairs of spaces into two non-breaking spaces, tabs into four non-breaking spaces and all line breaks into <br> elements. In XSLT 1.0, I'd do:
<xsl:template name="replace-spaces">
<xsl:param name="text" />
<xsl:choose>
<xsl:when test="contains($text, ' ')">
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-before($text, ' ')"/>
</xsl:call-template>
<xsl:text>  </xsl:text>
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-before($text, ' ')" />
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, ' ')">
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-before($text, ' ')"/>
</xsl:call-template>
<xsl:text>    </xsl:text>
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-before($text, ' ')" />
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($text, '
')">
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-before($text, '
')" />
</xsl:call-template>
<br />
<xsl:call-template name="replace-spaces">
<xsl:with-param name="text" select="substring-after($text, '
')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Not being able to use tail recursion is a bit of a pain, but it shouldn't be a real problem unless the text is very long.
An XSLT 2.0 solution would use <xsl:analyze-string>.
Really, I'd choose an editor which supports this correctly, rather than wrangling it through more XML.
I and a co-worker (Patricia Eromosele) came up with the following solution: (Is there a better solution?)
<p> <xsl:call-template name="prewrap"> <xsl:with-param name="text" select="text"/> </xsl:call-template> </p> <xsl:template name="prewrap"> <xsl:param name="text" select="."/> <xsl:variable name="spaceIndex" select="string-length(substring-before($text, ' '))"/> <xsl:variable name="tabIndex" select="string-length(substring-before($text, ' '))"/> <xsl:variable name="lineFeedIndex" select="string-length(substring-before($text, '
'))"/> <xsl:choose> <xsl:when test="$spaceIndex = 0 and $tabIndex = 0 and $lineFeedIndex = 0"><!-- no special characters left --> <xsl:value-of select="$text"/> </xsl:when> <xsl:when test="$spaceIndex > $tabIndex and $lineFeedIndex > $tabIndex"><!-- tab --> <xsl:value-of select="substring-before($text, ' ')"/> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:call-template name="prewrap"> <xsl:with-param name="text" select="substring-after($text,' ')"/> </xsl:call-template> </xsl:when> <xsl:when test="$spaceIndex > $lineFeedIndex and $tabIndex > $lineFeedIndex"><!-- line feed --> <xsl:value-of select="substring-before($text, '
')"/> <br/> <xsl:call-template name="prewrap"> <xsl:with-param name="text" select="substring-after($text,'
')"/> </xsl:call-template> </xsl:when> <xsl:when test="$lineFeedIndex > $spaceIndex and $tabIndex > $spaceIndex"><!-- two spaces --> <xsl:value-of select="substring-before($text, ' ')"/> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:text disable-output-escaping="yes">&nbsp;</xsl:text> <xsl:call-template name="prewrap"> <xsl:with-param name="text" select="substring-after($text,' ')"/> </xsl:call-template> </xsl:when> <xsl:otherwise><!-- should never happen --> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template>
Source: http://jamesjava.blogspot.com/2008/06/xsl-preserving-line-feeds-tabs-and.html
Not sure if this relevant, but isn't there a preservespace attribute and whatnot for xml?