displaying the result of xsl in cusomised format - xslt

I have the below xsl tag
<RectypeLegType>
<xsl:value-of select="../#id" />
</RectypeLegType>
and there can be two possible out come values of this as shown below..
1) <RectypeLegType>fixedLeg_612822</RectypeLegType>
2)<RectypeLegType>floatingLeg_194743</RectypeLegType>
but i want this value to be dispalyed as
<RectypeLegType>fixedLeg</RectypeLegType>
<RectypeLegType>floatingLeg</RectypeLegType>
now please advise how can i achieve this possible outcome i need to do cheanges in my please advise what changes need to be done

Assuming the underscore will always exist in the id attribute:
<RectypeLegType>
<xsl:value-of select="substring-before(../#id, '_')" />
</RectypeLegType>

Related

How can you apply concat(...) in a value-of directive in case of multiple nodes?

I am outputting the name node of each property node in a ; delimited string as following:
<xsl:value-of select="properties/property/name" separator=";" />
I want to alter this such that each element is prefixed with _. An example output should be:
_alpha;_beta;_gamma
I tried the following:
<xsl:value-of select="concat('_', properties/property/name)" separator=";" />
I want to use this to create an output node containing that string:
<my_node>
<xsl:value-of select="concat('_', properties/property/name)" separator=";" />
</my_node>
This gives an error when there are multiple properties:
XPTY0004: A sequence of more than one item is not allowed
as the second argument of fn:concat() (<name>, <name>)
Is there a way to get this working in XSLT 2.0/3.0?
I could resort to the XSLT 1.0 for-each solution as given in https://stackoverflow.com/a/57856287/12042211 (in which we are manually adding the separator), but I am wondering if something elegant in XSLT 2.0/3.0 is possible.
The answer is yes. XSLT 2.0 allows you to write expressions like this...
<xsl:value-of select="properties/property/concat('_', name)" separator=";" />
So, for each property it selects the concatenation of "_" with the name element.
Such syntax is not valid in XSLT 1.0 though.
In XSLT 3.0 I would tend to write this as
<xsl:value-of select="properties/property ! ('_' || name)" separator=";" />
and perhaps use string-join() instead of xsl:value-of. You haven't shown the context, but try to use xsl:value-of only when you really want a text node, not when you just want a string.

XML when statement doesn't work

The following is giving me the "memberstable is an unexpected token" error.
<xsl:when value-of memberstable/#member_cancontactthem =1>
<td bgcolor="#ff00ff">
<xsl:value-of select="You can contact this member"/></td>
</xsl:when>
I've used this to initialize it:
<xsl: value of select = "memberstable/#member_cancontactthem" />
The value in the DB is boolean, so either 1 or 0.
Until now, all suggestions will produce errors if I am not mistaken. xsl:when needs a test attribute:
<xsl:when test="memberstable[#member_cancontactthem='1']">
is the correct syntax. Also, xsl:when must be inside an xsl:choose element.
In general, please be careful with whitespace, and with hyphenations (for instance, value of is not the same as value-of) and make sure all attribute values are between quotes. XSLT must respect the rules of XML, which is not as forgiving as HTML.

xsl "value-of" math with "format-number" variables

I'm new to xsl and have a problem. I always get "NaN" when i try to do the following:
<xsl:variable name="amount" select="format-number(ARTICLE_PRICE/PRICE_LINE_AMOUNT, '0,00')" />
<xsl:variable name="quantity" select="format-number($quantity, '0,0#')"/>
<xsl:value-of select="format-number($amount * $quantity, '0,00')" />
Can someone tell me what i am doing wrong?
One possible reason out of several:
The result of format-number() is a string; if the string cannot be converted back to a number - for example, if it contains a comma - then you cannot multiply by it.
Well, if i do it like this:
<xsl:variable name="quantity" select="format-number($quantity, '0,0#')"/>
<xsl:value-of select="format-number(ARTICLE_PRICE/PRICE_LINE_AMOUNT * $quantity, '0,00')" />
It works. Still curious why it didn't work if i set the variable "amount"..
The 'NaN' value means you try to use format-number() on a value that is empty or not a valid number.
You have to test the value before using them as number, and formatting them before multiplying them is useless (if you don't use them elsewhere)

Manage flags in xslt?

All,
i am searching in a list of fields those who has the type clob and i am writing it separed by a comma like this [field1, field2, ... fieldn]
my problem is how to identify the first matched field to write it without comma ( i can't use position() because the first field matched can be the first of the list or the last of the list)
I want to make this algorithm in xslt,
variable is_first = TRUE;
if(is_first) {
do smthng;
isfirst = False;
}
Actually it is not possible to make something like this in xslt since variable are immutable. There probably could be workarounds but you have to specify your need in more details.
edit:
If your input is string with values separated by commas...
<xsl:variable name="inputString" select="'field1,field2,field3a,field4,field3b'" />
... you could use tokenize() functions...
<xsl:variable name="tokenized" select="tokenize($inputString, ',')" />
... and then select items corresponding to your condition
<!-- Select item corresponding to condition (e.g. it contains 3). Take first one if there are several such items -->
<xsl:value-of select="$tokenized[contains(., '3')][1]" />
Edit2:
You can use separator attribute of xsl:value-of (xslt 2.0) for output of delimited values.
Assuming following variable
<xsl:variable name="list">
<item>first</item>
<item>second</item>
<item>third</item>
</xsl:variable>
this <xsl:value-of select="$list/item" separator="," /> makes desired output first,second,third
You need to write this using functional code rather than procedural code. It's not possible to do the conversion without seeing the context (it's much easier to work from the problem rather than from the solution in a lower-level language).
But the most common equivalent in XSLT would take the form
<xsl:for-each select=".....">
<xsl:if test="position() = 1"><!-- first time code --></xsl:if>
....
</xsl:for-each>

XSL: Combining grouping and call-template

I've read with interest the techniques available on the web to extract a unique list of items from a XML file containing duplicates using XSL.
These range into 2 categories:
1) The Muenchian method (example: http://www.jenitennison.com/xslt/grouping/)
2) Or the previous-sibling look-up
These both rely on an XPath expression to select the data to group by.
However, in the XML file that I'm trying to work out, the data is not present "natively" in the XML file. I am using a xsl:template to compute some aggregated data from my elements. And I would like to group based on the aggregated data.
For example I have:
<filmsreview>
<record><data name='movie'>Star Wars</data><data name='ratings'>John:Good, Mary:Good</data></record>
<record><data name='movie'>Indiana Jones</data><data name='ratings'>John:Good, Mary:Bad, Helen:Average</data></record>
<record><data name='movie'>Titanic</data><data name='ratings'>John:Bad, Helen:Good</data></record>
</filmsreview>
I know that the structuration of data is not perfect and that by creating sub-elements I could do something easier, but I cannot change the data source easily, so let's take this as a challenge.
And I would like to build a recap where I have John's distinct ratings:
John's ratings:
Good
Bad
I have a xsl:template that can take a record element and return John's rating for this record:
Example:
<xsl:template name="get_rating">
<xsl:param name="reviewer" />
<!-- I use some string manipulation, and xsl:value-of to return the review for John-->
</xsl:template>
I can just call it under a xsl:for-each to get the exhaustive list of John's review. But I cannot combine this call with any of the methods to get unique values.
Do I have to use an intermediary XSL to convert my XML file to a more structured way? Or can I do in a single step?
Many thanks
Gerard
Hmm... This should be possible using xslt variables and the nodeset method, perhaps something like this:
<xsl:variable name="_johnsRatings">
<xsl:apply-templates select="/" mode="johnsRatings" />
</xsl:variable>
<xsl:variable name="johnsRatings" select="msxsl:node-set($_johnsRatings)" />
<xsl:template match="/" mode="johnsRatings">
<Ratings>
<xsl:for-each select="/filmsReview/record/data[#name='ratings']">
<Rating><xsl:call-template name="get_rating" /></Rating>
</xsl:for-each>
</Ratings>
</xsl:template>
At this point, it should be possible to query the $johnsRatings variable using standard XPath queries, and you can use either of the two methods you mentioned above to retrieve unique values from it...
Hope that helps
EDIT:
I don't know what XSLT engine you are using, I assumed you have access to the msxsl:node-set() function. However, most XSLT processors have similar methods, so you might have to search around for an equivalent method in your processor