XSLT/XPath : No upper-case function in MSXML 4.0? - xslt

I try to use upper-case() in an XPATH, my parser is MSXML 4.0, and I get :
upper-case is not a valid XSLT or XPath function.
Is it really not implemented ?

There are no functions in xslt 1.0 to convert to uppercase or lowercase. Instead do the following:
If it is required in a lot of places:
Declare these two xsl variables (this is to make the xslt more readable)
<!-- xsl variables up and lo and translate() are used to change case -->
<xsl:variable name="up" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lo" select="'abcdefghijklmnopqrstuvwxyz'"/>
And use them in your translate function to change the case
<xsl:value-of select="translate(#name,$lo,$up)"/>
If you need to use it in just one place, no need to declare variables
<xsl:value-of select="translate(#name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>

Maybe this can help you:
translate(string, string, string)
The translate function takes a string and, character-by-character, translates characters which match the second string into the corresponding characters in the third string. This is the only way to convert from lower to upper case in XPath. That would look like this (with extra white space added for readability). This code would translate the employee last names to upper case and then select those employees whose last names begin with A.
descendant::employee[
starts-with(
translate(#last-name,
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
"A"
)
]
If the second string has more characters than the third string, these extra characters will be removed from the first string. If the third string has more characters than the second string, the extra characters are ignored.
(from http://tutorials.beginners.co.uk/professional-visual-basic-6-xml-part-1-using-xml-queries-and-transformations.htm?p=3)

Related

Acute accent character eliminate using xslt

I am trying to either eliminate or replace the acute accent character with a simple single quote character in xslt 1.0.This is what I have tried so far and none of them replace that character. What could be wrong with my translate construct?
<xsl:value-of select="translate(HeaderFields/Name,'#xb4','')"/>
<xsl:value-of select="translate(HeaderFields/Name,'0xb4','')"/>
<xsl:value-of select="translate(HeaderFields/Name,'´','\'')"/>
Try:
<xsl:value-of select='translate(HeaderFields/Name,"´","&apos;")'/>
Note the exchange of double and single quotation marks - see explanation at: https://www.w3.org/TR/1999/REC-xpath-19991116/#section-Introduction
You can express an acute accent as '´' or as ´. Neither '#xb4' nor '0xb4' is correct. (Were you just guessing?)
Expressing the single quote is a bit trickier. In XSLT 2.0 you can write it as '''', but that doesn't work in 1.0. In 1.0 the best way is to use a variable:
<xsl:variable name="apos">'</xsl:variable>
<xsl:value-of select="translate(HeaderFields/Name,'´',$apos)"/>
Finally, you need to be aware that an acute accent might not be a free-standing Unicode character; it might be combined with the character that it modifies, so for example á could be expressed as the single code point xE1. To ensure that it is a separate character you need to convert the text to decomposed normal form, which can be done in 2.0 using the normalize-unicode() function, but this is not available in 1.0.

XSLT/XPath quoting: XPath within an XPath-Function within XSLT

Here we're using double quotes at the XSLT level; single quotes at the XPath function level, but when we need to embed an XPath expression within the XPath function, how do we quote that?
<xsl:value-of select="document('price-list.xml','/im_prices/row/UPC_Code[text()='abc']"/>
^^^^^
(scroll to the right)
Not sure about that, I have always used the node-set form of:
<xsl:value-of select="document('price-list.xml')/im_prices/row/UPC_Code[text()='abc']"/>
but that may be vendor specific (however, have never known it not to work!)
The second argument of document() is a node-set, not a string, so the problem should not arise. However, there are of course other cases where it can arise.
In XSLT 2.0:
if you want to include the attribute delimiter in a string, escape it as " or &apos;
if you want to include the string delimiter in a string, double it as '' or "".
In XSLT 1.0, the second option is not available. You can get around it either
(a) by swapping the character used for the attribute delimiter and the string delimiter
(b) by using concat() to build the string

XSLT substring and hash tag

Can someone tell me why this is not working?
Throughout my document I have several column breaks marked as follows: <cb ed="#S" n="45rb"/>
The hash tag is there to refer to another element where the source document is identified.
Now I want to display the column break in the following document. So that it looks like this:
|S45rb|. I thought I could use a simple substring function to get rid of the hash tag like so.
<xsl:template match="TU:cb">
<xsl:variable name="hashms"><xsl:value-of select="//TU:cb/#ed"/></xsl:variable>
<xsl:variable name="ms"><xsl:value-of select="substring($hashms,1,1)"/></xsl:variable>
<span>| <xsl:value-of select="$ms"/> <xsl:value-of select="//TU:cb/#n"/> |</span>
</xsl:template>
When I do it this way I get the following result: |#75ra|. Shouldn't the first 1 in the argument refer to the first character of the string and then the second 1 tell it to move over one character and leave me with the desired S? Instead I don't get the S but only the hash tag. Is there something about hash tags and strings I do not know?
Thanks for your help.
XSL is not 0 base, if you want to start at the second character (after the #), it should be 2 rather than 1.
http://www.w3schools.com/Xpath/xpath_functions.asp
substring($hashms,2,1) = S
You can also omit the length, which might be of benefit for extensibility later on. Especially if whatever comes after the # is the identifier, why limit your code?
substring($hashms,2) = S
substring('#S2',2) = S2

How to express a string containing both apostrophes and quotes in XPath?

I'll spare you the details because they would be needlessly confusing. Long story short, I'm using XSLT 1.0 to generate XSL documents, I'm trying to compare a variable to a literal string, and that string may contain quotes and apostrophes.
For the sake of simplicity, let's say that this literal is composed of two characters: a quote followed by an apostrophe. In reality, it can be any text really. Is there a simpler way to do this:
<xsl:if test="$var = concat('"', "'")">
than this?
<xsl:variable name="str">"'</xsl:variable>
<xsl:if test="$var = $str">
I have checked XPath's specs and there doesn't seem to be a way to escape characters, so the following would not work as desired:
<xsl:if test="$var = '"&apos;'">
Thanks!
There's no way to do it neatly in XPath 1.0. In XPath 2.0, you can escape both kinds of quotes by doubling.
& quot;& amp;&(!)apos; -looks much better, but what did you want to get?
In anyway: once I have written application that deals with producing of Javascript over XSLT.
The same problem with huge number of & quot;,... we solved in 2 ways:
Declare global xsl:param, $q - looks shorter than & quot;
Use 'translate' XPath function, make assumption '!' - is a & quot;, # is a & amp; ..

lower case the first character of a string using only xslt 1.0

I have seen patterns for translating a string into lower (or upper case) using the translate function for folks stuck using xslt 1.0.
Is there a elegant way of just making the first letter of a string lowercase?
TestCase => testCase
If your string were, for example, in an attribute called name:
<xsl:value-of select="concat(translate(substring(#name, 1, 1), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), substring(#name, 2))"/>
You should be able to combine substring and concat with translate to do it like so:
concat(translate(substring(s,1,1), $smallcase, $uppercase),substring(s,2))
Use the XPath translate function, having separated the string into first character and the rest. This will require somewhat long winded XSLT using multiple variables to hold intermediate results.
XSLT has a substring function, so you could use that pattern with the substring function to get what you want.