Strip leading spaces only - xslt

Given element:
<comments> comments
go here
</comments>
How can I strip what may be multiple leading space characters. I cannot use normalize space because I need to retain newlines and such. XSLT 2.0 ok.

In XPath 1.0 (means XSLT 1.0, too):
substring($input,
string-length(
substring-before($input,
substring(translate($input, ' ', ''),
1,
1)
)
) +1
)
Wrapped in an XSLT transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="input"
select="string(/*/text())"/>
<xsl:template match="/">
'<xsl:value-of select=
"substring($input,
string-length(
substring-before($input,
substring(translate($input, ' ', ''),
1,
1)
)
) +1
)
"/>'
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<t> XXX YYY Z</t>
the correct, wanted result is produced:
'XXX YYY Z'

Use the replace() function:
replace($input,'^ +','')
That handles leading space characters only up to the first non-space. If you want to remove all leading whitespace characters (i.e. space, nl, cr, tab) up to the first non-whitespace, use:
replace($input,'^\s+','')

Related

How to remove last N character using XSLT

I have following code
<xsl:value-of select=concat(substring(DBColumn, string-length(DBColumn)-3),concat('-',DBColumn))
It results me
230-Virginia-230.
I want it as 230-Virginia.
Originally in database it is as Virginia-230
Furthermore
ABC, 230-Virginia
How to trim whitespace in the same mentioned code so that it should look like as follow ABC,230-Virginia
It's not clear what exactly your question is.
To answer the question as stated in your title: you can remove the last N characters from a string using:
substring($string, 1, string-length($string) - $N)
Trying to illustrate with an input document that contains the data that you mentioned:
<input>
<DBColumn>Virginia-230</DBColumn>
<other>ABC </other> <!-- N.B. trailing space -->
</input>
This XSLT 3.0 stylesheet does some of the things that you mentioned in the "proposed value". I've also included the input value and the "old-value" with the value-of expression that you mentioned in your post.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
exclude-result-prefixes="#all">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/input">
<output>
<input-value><xsl:value-of select="DBColumn" /></input-value>
<old-output-value>
<xsl:value-of
select="concat(substring(DBColumn, string-length(DBColumn)-3),
concat('-', DBColumn))"/>
</old-output-value>
<proposed-value>
<xsl:value-of
select="normalize-space(other)
|| ',' ||
string-join(reverse(tokenize(DBColumn, '-')), '-')"
/>
</proposed-value>
</output>
</xsl:template>
</xsl:stylesheet>
which produces:
<output>
<input-value>Virginia-230</input-value>
<old-output-value>-230-Virginia-230</old-output-value>
<proposed-value>ABC,230-Virginia</proposed-value>
</output>
For an xsl:value-of() that I believe works in XSLT1.0 (but I won't guarantee), you could try:
<xsl:value-of
select="concat(other, ',',
substring-after(DBColumn, '-'),
'-',
substring-before(DBColumn, '-'))" />
which does not address the trailing space in other but at least suggests how to reverse the two values around the '-' char in DBColumn.
For suggestions on removing leading/trailing spaces on string, see: XSLT 1.0 to remove leading and trailing spaces

Character does not show in XSLT

In XSLT performed a normalize-space and not done well, it's not a whitespace is a character invisible.
Element
<div class='tyreNameComplete'> WinterContact TS800 </div>
XSLT:
translate(//x:div[#class='tyreNameComplete'], ' ', '')
the element with strange characters:
WinterContact TS800
The character is:
no show.
I hope the result is:
WinterContact TS800
I need to clean to get only what you need. How would you treat this case?. Thanks.
The solution:
translate(//x:div[#class='tyreNameComplete'], '
', '')
contain invisible character after
, to view visualize the file in linux terminal and copy the character in my xslt.
Using this source XML:
<element>
WinterContact TS800
</element>
And this template:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<collapsed><xsl:value-of select="normalize-space(element)"/></collapsed>
</xsl:template>
</xsl:stylesheet>
I get this output:
<collapsed>WinterContact TS800</collapsed>
This appears to be what you want?

how can we fetch value of data in line feed manner by using xslt

here i have pasted a sample xml of 50G, earlier i used fetch the data from this below tag with the help of using crlf but now i want to fetch by using line feed ,because i need data correctly what if i ask like suppose i want linefeed 1 content means AE012345677890
similarly line feed 2 means it should fetch Bank code by using xslt how do i can call line feed .
<local>
<message>
<block4>
<tag>
<name>50G</name>
<value>AE012345677890
Bank code
country name
country code</value>
</tag>
</block4>
</message>
</local>
output required :
AE012345677890,Bank code,country name,country code
It's obviously bad use of XML. The point of XML is that you shouldn't need any other parsing and here you do need one, namely splitting on newline. Anyway, when you already have that, you can split on newline using the core XPath functions substring-before and substring-after.
First line should be something like
substring-before(value, '
')
(that's an xpath expression, so you have to put it into or similar tag) and the remaining lines should be
substring-after(value, '
')
You can combine these two, so second line is
substring-before(substring-after(value, '
'), '
')
third line is
substring-before(substring-after(substring-after(value, '
'), '
'), '
')
etc.
PS: I am not sure whether you need to use
or \n for newline.
Depending on the value space for the different constituent types (e.g. if it is known that they don't contain a space), one of these simple XSLT 1.0 solutions may be what you need:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="value">
<xsl:value-of select=
"translate(., '
', ',')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Produces:
AE012345677890,Bankcode,countryname,countrycode
And this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="value">
<xsl:value-of select=
"normalize-space(translate(., '
', ','))"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
produces:
AE012345677890, Bank code, country name, country code
If none of these two XSLT 1.0 transformation satisfies your requirements, you may need to perform a trim operation. There is a trim function/template in FXSL -- ready to use.
II. A quick XSLT 2.0 solution:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="value">
<xsl:variable name="vLines" select="tokenize(., '
?
')"/>
<xsl:for-each select="$vLines">
<xsl:value-of select=
"translate(replace(., '(^[ \t\r]+)|([ \t\r]+$)', '~~'), '~', '')"/>
<xsl:if test="not(position() eq last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
produces exactly the wanted result:
AE012345677890,Bank code,country name,country code
If you're using XSLT 2.0, you can also do this using the tokenize function:
<xsl:template match="value">
<!-- loop through each segment that's before a line break, output
its normalised value and add a comma if required -->
<xsl:for-each select="tokenize(., '
')">
<xsl:value-of select="normalize-space(current())"/>
<xsl:if test="not(position()=last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
This produces the desired result:
AE012345677890,Bank code,country name,country code
(As Dimitre Novatchev points out below, it will also collapse multiple white space, ie: spaces and tabs inside each line, into one single space, so you might want to experiment and see if that's okay with your data)
If you are limited to XSLT 1.0, you may be able to implement the EXSLT library which also contains tokenize (see the tokenize page and click on "How To" in the upper lefthand menu for more information on implementing the library).

xsl:character-map to replace special characters

Given an element with a value of:
<xml_element>Distrib = SU & Prem &lt;&gt; 0</xml_element>
I need to turn &lt; or &gt; into < or >
because a downstream app requires it in this format throughout the entire XML document. I would need this for quotes and apostrophes too. I am tryinging a character-map in XSLT 2.0.
<xsl:character-map name="specialchar">
<xsl:output-character character="&apos;" string="&apos;" />
<xsl:output-character character=""" string="&quot;" />
<xsl:output-character character=">" string="&gt;" />
</xsl:character-map>
The <xsl:character-map> instruction can be used to serialize a single character to any string. However this problem requires more than one character (an ampersand followed by another character to be replaced.
<xsl:character-map> cannot be used to solve such problems.
Here is a solution to this problem, using the XPath 2.0 replace() function:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select=
'replace(
replace(
replace(., "&lt;", "<"),
"&gt;",
">"
),
"&apos;",
"&apos;"
)
'/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<xml_element>Distrib = SU & &apos;Prem &lt;&gt; 0</xml_element>
the wanted result is produced:
<xml_element>Distrib = SU & 'Prem <> 0</xml_element>

How to remove spaces from the end of text in an element. (XSL)

Does anyone know what XSL code would remove the trailing whitespace after the last word in an element?
<p>This is my paragraph. </p>
Thanks!!
Look at the normalize-space() XPath function.
<xsl:template match="p">
<p><xsl:value-of select="normalize-space()" /></p>
</xsl:template>
Be careful, there is a catch (which might or might not be relevant to you):
The [...] function returns the
argument string with whitespace
normalized by stripping leading and
trailing whitespace and replacing
sequences of whitespace characters by
a single space.
This means it also removes all line breaks and tabs and other whitespace and turns them into a single space.
EDIT: Significant simplification of the code, thanks to a hint from Tomalak.
Here is an XPath 2.0 / XSLT 2.0 solution, which removes only the trailing spaces:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:output method="text"/>
<xsl:template match="text()">
"<xsl:sequence select="replace(., '\s+$', '', 'm')"/>"
</xsl:template>
</xsl:stylesheet>
When this is applied on the following XML document:
<someText> This is some text </someText>
the wanted result is produced:
" This is some text"
You can see the XSLT 1.0 solution (implementing almost the same idea), which uses FXSL 1.x, here:
http://www.biglist.com/lists/xsl-list/archives/200112/msg01067.html