I am trying to format a string to remove spaces from a phone number and am having trouble. The code I am using is:
<xsl:choose>
<xsl:when test="EmployeeCellPhone != ''">
<xsl:value-of select="translate(EmployeeCellPhone, ' ',' ')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="translate(EmployeeHomePhone, ' ',' ')"/>
</xsl:otherwise>
</xsl:choose>
However, it does not work. Can anyone point me in the right direction? The current output looks like this: 123 456 7890 and I need the results to look like: 1234567890
You are replacing a space with a space.
I also don't think you need a condition if you always want to replace the spaces.
<xsl:value-of select="translate(EmployeeCellPhone, ' ', '')"/>
See it working here : https://xsltfiddle.liberty-development.net/naZYrpC
Related
In XSLT 2.0 I have a parameter than comes in as a delimited string of document names like:
ms609_0080.xml~ms609_0176.xml~ms609_0210.xml~ms609_0418.xml
I tokenize() this string and cycle through it with xsl:for-each to pass each document to a key. The results from the key I then assemble into a comma-delimited string to output to screen.
<xsl:variable name="list_of_corresp_events">
<xsl:variable name ="tokenparam" select="tokenize($paramCorrespdocs,'~')"/>
<xsl:for-each select="$tokenparam">
<xsl:choose>
<xsl:when test=".[position() != last()]">
<xsl:value-of select="document(concat($paramSaxondatapath, .))/(key('correspkey',$correspid))/#xml:id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(document(concat($paramSaxondatapath, .))/(key('correspkey',$correspid))/#xml:id, ', ')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
Everything works fine except that when I output the variable $list_of_corresp_events it looks like the following, with an unexpected trailing comma:
ms609-0080-2, ms609-0176-1, ms609-0210-1, ms609-0418-1,
Ordinarily the last comma should not appear based on test=".[position() != last()]" ? Possibly positions don't work for tokenized data? I didn't see a way to apply string-join() to this.
Many thanks.
Improving on the solution from #zx485, try
<xsl:for-each select="$tokenparam">
<xsl:if test="position()!=1">, </xsl:if>
<xsl:value-of select="document(concat($paramSaxondatapath, .))/(key('correspkey',$correspid))/#xml:id"/>
</xsl:for-each>
Two things here:
(a) you don't need to repeat the same code in both conditional branches
(b) it's more efficient to output the comma separator before every item except the first, rather than after every item except the last. That's because evaluating last() involves an expensive look-ahead.
Change
<xsl:when test=".[position() != last()]">
to
<xsl:when test="position() != last()">
Then it should all work as desired.
It seems you can simplify this to
<xsl:variable name="list_of_corresp_events">
<xsl:value-of select="for $t in tokenize($paramCorrespdocs,'~') document(concat($paramSaxondatapath, $))/(key('correspkey',$correspid))/#xml:id" separator=", "/>
</xsl:variable>
or with string-join
<xsl:variable name="list_of_corresp_events" select="string-join(for $t in tokenize($paramCorrespdocs,'~') document(concat($paramSaxondatapath, $))/(key('correspkey',$correspid))/#xml:id, ', ')"/>
I have the below condition that I have wriiten in xsl below..
as i have getting an value in xml of fpml:tradeId now it can be there in xml or it can not be there for example as shown below..
<fpml:tradeId tradeIdScheme=""></fpml:tradeId>
or it can contain value also
<fpml:tradeId tradeIdScheme="">10381159400</fpml:tradeId>
as advise i have change the implementation to but still not working ..
<xsl:if test = "fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId = ' '">
<xsl:value-of select="'null'" />
</xsl:if>
</ContractID>
so to deal with this problem i have come up with this below xsl , now the problem comes is that for the cases where tradeId is not there in xml it is not putting null string please advise is my below implementation of
xsl is correct
<xsl:if test = "fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId != ' '">
<xsl:choose>
<xsl:when test="contains(fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId,'-')">
<xsl:value-of select="substring-before(fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId,'-')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId" />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test = "fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId = ' '">
<xsl:value-of select="'null'" />
</xsl:if>
</ContractID>
as advise new implemetaion done but it is still not working..
<xsl:if test="normalize-space(fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId)">
<xsl:choose>
<xsl:when test="contains(fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId,'-')">
<xsl:value-of select="substring-before(fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId,'-')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId" />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:if test = "fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId = ' '">
<xsl:value-of select="'null'" />
</xsl:if>
</ContractID>
You're testing for
fpml:tradeId = ' '
which it doesn't in your example - the value of your fpml:tradeId is the empty string, not a string containing a space. Instead of comparing the value against ' ' for the first case you could use a test of
<xsl:if test="normalize-space(
fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId)">
In XPath a string coerces to a boolean by treating it as false if the string is empty and true if it isn't, so the test will pass if the tradeId value contains at least one non-whitespace character, and fail if it is completely empty or contains only whitespace.
For the second case
<xsl:if test="not(normalize-space(
fpml:dataDocument/*/*/fpml:partyTradeIdentifier[2]/fpml:tradeId))">
would give you the reverse test - true if the string is all whitespace or empty, false if it isn't (or just use a choose with an otherwise clause instead of two opposing if tests).
i am trying to do equal comparison of negative number, but i dont see any output. below is the code.
<xsl:variable name="OwnershipStatus" select="Veh_Ownsp[Veh_Ownsp_ID=$OwnerData1/Veh_Ownsp_ID]/Ownsp_Cntl_Type_ID"/>
Here OwnershipStatus is returninenter code hereg -1
xsl:choose>
<xsl:when test="$OwnershipStatus = -1" >
<xsl:value-of select="Or"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="And"/>
</xsl:otherwise>
</xsl:choose>
I guess you are trying to hardcode 'Or' and 'And' in case of condition getting evaluated to true and false, respectively. Since the values are literal they should be enclosed with single quotes as shown below:
<xsl:choose>
<xsl:when test="$OwnershipStatus = -1" >
<xsl:value-of select="'Or'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'And'"/>
</xsl:otherwise>
I think I have this working but I need advice. I'd like to know if this is a good setup for the requirement that I have.
I've got a requirement to apply different transformation rules to an element based on what is contained in that element. I've tried to search for 'xsl' and 'choose', 'contains', 'substring'. I can't seem to find a solution applicable to this situation.
Here are the various scenarios for this element:
If it begins with U, I need everything before the '/'
Original Value: UJXXXXX/001
Transformed : UJXXXXX
If it begins with ECG_001 I need everything after ECG_001
Original Value: ECG_0012345678
Transformed : 12345678
If it does not meet the above criteria and contains a '/' take everyting after the '/'
Original Value: F5M/12345678
Transformed : 12345678
If it does not meet 1,2, or 3 just give me the value
Original Value : 12345678
Transformed : 12345678
Here is what I have so far:
<xsl:variable name="CustomerPO">
<xsl:choose>
<xsl:when test="contains(substring(rma/header/CustomerPO,1,1), 'U')">
<xsl:value-of select="substring-before(rma/header/CustomerPO,'/')"/>
</xsl:when>
<xsl:when test="contains(rma/header/CustomerPO, 'ECG_001')">
<xsl:value-of select="substring-after(rma/header/CustomerPO,'ECG_001')"/>
</xsl:when>
<xsl:when test="contains(rma/header/CustomerPO, '/')">
<xsl:value-of select="substring-after(rma/header/CustomerPO, '/')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="rma/header/CustomerPO"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Any feedback on potential loopholes or a more efficient way to accomplish this is appreciated.
Thanks.
Your XSLT looks fine. You might consider using the starts-with function rather than substring, I find it easier to read, but I am not sure it is any faster.
My own style would be to use template rules.
<xsl:template match="CustomerPO[starts-with(., 'U')]">
<xsl:value-of select="substring-before(., '/')"/>
</xsl:template>
<xsl:template match="CustomerPO[starts-with(., 'ECG_001')]">
<xsl:value-of select="substring-after(., 'ECG_001')"/>
</xsl:template>
etc.
I need to perform a find and replace using XSLT 1.0 which is really suited to regular expressions. Unfortunately these aren't available in 1.0 and I'm also unable to use any extension libraries such as EXSLT due to security settings I can't change.
The string I'm working with looks like:
19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson
I need to replace the numbers and ; # characters with a ,. For example the above would change to:
John Smith, Ben Reynolds, Terry Jackson
I know a recursive string function is required, probably using substring and translate, but I'm not sure where to start with it.
Does anyone have some pointers on how to work this out? Here's what I've started with:
<xsl:template name="TrimMulti">
<xsl:param name="FullString" />
<xsl:variable name="NormalizedString">
<xsl:value-of select="normalize-space($FullString)" />
</xsl:variable>
<xsl:variable name="Hash">#</xsl:variable>
<xsl:choose>
<xsl:when test="contains($NormalizedString, $Hash)">
<!-- Do something and call TrimMulti -->
</xsl:when>
</xsl:choose>
</xsl:template>
I'm hoping you haven't simplified the problem too much for asking it on SO, because this shouldn't be that much of a problem.
You can define a template and recursively call it as long as you keep the input string's format consistent.
For example,
<xsl:template name="TrimMulti">
<xsl:param name="InputString"/>
<xsl:variable name="RemainingString"
select="substring-after($InputString,';#')"/>
<xsl:choose>
<xsl:when test="contains($RemainingString,';#')">
<xsl:value-of
select="substring-before($RemainingString,';#')"/>
<xsl:text>, </xsl:text>
<xsl:call-template name="TrimMulti">
<xsl:with-param
name="InputString"
select="substring-after($RemainingString,';#')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$RemainingString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I tested this template out with the following call:
<xsl:template match="/">
<xsl:call-template name="TrimMulti">
<xsl:with-param name="InputString">19;#John Smith;#17;#Ben Reynolds;#1;#Terry Jackson</xsl:with-param>
</xsl:call-template>
</xsl:template>
And got the following output:
John Smith, Ben Reynolds, Terry Jackson
Which seems to be what you're after.
The explanation of what it is doing is easy to explain if you're familiar with functional programming. The InputString parameter is always in the form [number];#[name];#[rest of string]. Each call of the TrimMulti template chops off the [number];# part and prints off the [name] part, then passes the remaining expression to itself recursively.
The base case is when InputString is in the form [number];#[name], in which case the RemainingString variable won't contain ;#. Since we know this is the end of the input, we don't output a comma this time.
If the ';' and '#' characters are not valid in the input because they are delimiters then why wouldn't the translate function work? It might be ugly (you have to specify all valid characters in the second argument and repeat them in the third argument) but it would be easier to debug.
translate($InputString, ';#abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ', ', abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUZ0123456789,- ')