XSLT 1.0 amount fields have to have at least 2 decimals - xslt-1.0

I have two xmls.There is a amount field which can contains values like 54.2,54.23,54.234,54.234567.
Would someone please tell me how can I make sure that atleast two decimal places will appear in the output xml.Currently 54.2 gets converted to 54,2 , but I want it to be 54,20

You can use the format-number() function to convert a number into a string in a given format.
At least two decimal places will be appeared if you use this "#.00##########" format string.
If you have an xml file which can contains values like 54.2,54.23,54.234,54.234567:
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<price>54.2</price>
<price>54.23</price>
<price>54.234</price>
<price>54.234567</price>
</catalog>
You can convert the numbers with an xslt like this to get at least two decimal places
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="/catalog/price">
<xsl:value-of select='format-number(., "#.00##########")'/><br />
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Then the output:
54.20
54.23
54.234
54.234567

Related

Need to create a function with argument in XSLT 1.0

Need small help in creating a function with parameter and that can be used in my template. Tried many things but nothing worked out. Below is my sample code :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:math="http://exslt.org/math"
xmlns:func="http://exslt.org/functions"
xmlns:my="http://exslt.org/my"
exclude-result-prefixes="my"
extension-element-prefixes="my math func">
<xsl:output indent="yes" method="xml" />
<xsl:variable name="functionTest11">
<xsl:value-of select="my:calXY('aa')" />
</xsl:variable>
<xsl:template match="/">
<svg xmlns="http://www.w3.org/2000/svg">
<xsl:variable name="functionTest22">
<xsl:value-of select="my:calXY" />
</xsl:variable>
<xsl:comment>functionTest <xsl:copy-of
select="$functionTest22" /></xsl:comment>
</svg>
</xsl:template>
<func:function name="my:calXY">
<xsl:comment>functionHello </xsl:comment>
<xsl:param name="string1" select="''"/>
<func:result>
<xsl:value-of select="concat(10,'|',10)" />
</func:result>
</func:function>
</xsl:stylesheet>
I don't have convenient access (that I know of) to Xalan, which appears to be the XSLT processor you are using. So I cannot test any conjectures about the origin of your problem.
But it would surprise me a great deal if putting an output instruction like xsl:comment before the first (and only) xsl:param were correct. (It surprises me that you don't report any error messages from the stylesheet compiler. But it's clear from the error message you quote that Xalan has not successfully compiled the function.) It's not clear what you are trying to accomplish by having your function return both a comment node and the string value '10|10', but this is probably not the way to accomplish it.
On the assumption that the xsl:comment instruction is an attempt to verify that the function has in fact been evaluated, I'd try something like
<func:function name="my:calXY">
<xsl:param name="string1" select="''"/>
<func:result select="concat(10,'|',10)" />
</
[In an earlier version of this answer, I speculated that func:result is not needed here; my error. It does appear to be needed.]
You ask for a complete stylesheet. The following stylesheet functions as expected when run with xsltproc. (As I noted above, I don't have a convenient way to run Xalan.)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:func="http://exslt.org/functions"
xmlns:my="http://example.org/my"
exclude-result-prefixes="my"
extension-element-prefixes="func">
<xsl:output indent="yes" method="xml" />
<xsl:template match="/">
<xsl:message>Result is <xsl:value-of select="my:dummy('foo')"/></xsl:message>
<output>
<test><xsl:value-of select="my:dummy('bar')"/></test>
<test><xsl:value-of select="my:dummy('baz')"/></test>
</output>
</xsl:template>
<func:function name="my:dummy">
<xsl:param name="s" select="'foo'"/>
<func:result select="concat($s,'|',$s)" />
</func:function>
</xsl:stylesheet>

Handling 0x19 in XSLT 1.0

I have encountered a problem when input xml contains the character 0x19. I have created a demo xslt to reproduce the issue.
My demo xslt looks like this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="param1"/>
<xsl:template match="/">
<Value>
<xsl:value-of select="$param1"/>
</Value>
</xsl:template>
</xsl:transform>
I am passing the character 0x19 as param1. The below output gets generated.
<Value></Value>
which is an invalid xml. How can I get it right?
You are correct that
<Value></Value>
is not well-formed XML 1.0 - XML 1.0 does not allow any control characters below U+0020 except U+0009 (tab), U+000A (LF) and U+000D (CR), not even when expressed as numeric character references, so it is simply not possible to include that character in an XML 1.0 document. The processor is wrong to produce that output, it should raise an error to complain that you've tried to insert an illegal character in the output.
However it is well formed XML 1.1, which allows control characters as &# references but not as literals. If your processor supports this (and the donwnstream components that will be receiving your output support it too) then it may be sufficient to add version="1.1" to the xsl:output instruction
<xsl:output method="xml" indent="yes" version="1.1"/>
to tell it to output XML 1.1 instead of XML 1.0.

XSLT Data Map with the character < in the data

I'm writing an XSLT data map from one XML schema to another XML schema. The target schema has a String field that will have a copy of the original XML in it. I know that I must convert the control characters in the XML to < and >. I have done that. The issue I'm having is that the data in the XML also has < and > in it as well. This causes problems because I'm sending the XML to a WCF-SQL adapter and when it hits the < in my data it attempts to convert that to < causing XML validation failure.
Here is a snippet of my XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="*" mode="serialize">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialize"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="/">
<proc_Insert xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo">
<StagingXML>
<xsl:variable name="nodestring">
<xsl:apply-templates select="*" mode="serialize"/>
</xsl:variable>
<xsl:value-of select="$nodestring"/>
</StagingXML>
</proc_Insert>
</xsl:template>
</xsl:stylesheet>
You need to quote the content, a truely ancient bit of code (predating xslt 1.0 I think:-) that does that is to be found
http://www.openmath.org/cdfiles2/xsl/verb.xsl
although there are newer versions around as well/

Getting particular substring using xslt1.0

I have a string as below.
<freeForm>
<text>mnr.getValue().put("xyz","pqr");</text>
</freeForm>
From the above xml portion i need to get the string xyz.
Please provide pointers to achieve the same using xslt1.0.
Use this XPath expression:
substring-before(
substring-after(/*/*, &apos;"&apos;),
&apos;"&apos;
)
Here is a short, complete XSLT transformation that evaluates this XPath expression and outputs the result of evaluating it:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select=
'substring-before(
substring-after(/*/*, &apos;"&apos;),
&apos;"&apos;
)'/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<freeForm>
<text>mnr.getValue().put("xyz","pqr");</text>
</freeForm>
the wanted, correct result is produced:
xyz

XSLT-1.0 can a variable be used to access to other nodes?

With a simple XML like this
<value>
<num>
<accession>111</accession>
<sequence>AAA</sequence>
<score>4000</score>
</num>
</value>
I want to know if it is possible to access to a particular node from a node previously stored in a variable. The XSLT code is very short and explains better what I want to say
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/value/num">
<xsl:variable name="node">
<xsl:copy-of select="current()"/>
</xsl:variable>
<root>
<xsl:copy-of select="$node"/>
</root>
</xsl:template>
</xsl:stylesheet>
So I store the node in the variable "node". Then I can print the contents of the node with $node.
(EDIT) XML output
<root>
<num>
<accession>111</accession>
<sequence>AAA</sequence>
<score>4000</score>
</num>
</root>
What I want to do is to print the contents of a sub-node, like this
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/value/num">
<xsl:variable name="node">
<xsl:copy-of select="current()"/>
</xsl:variable>
<root>
<xsl:copy-of select="$node/accession"/>
</root>
</xsl:template>
</xsl:stylesheet>
But it gives an error (Component returned failure code: 0x80600008 [nsIXSLTProcessor.transformToFragment]) (check here)
(EDIT) The XML that I would want is
<root>
<accession>111</accession>
</root>
NOTE: The question is not how can I get this output. The question is how, using a variable as in the XSLT provided, can I get this output.
(EDIT:SOLVED)
Actually it is possible, but as pointed out in the comments, the value of a variable has to be assigned with the "select" attribute if a node-set is required. So this code was not working since the variable had a tree fragment instead of a node-set stored in it (read more information here)
Thanks!
Try this:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/value">
<root>
<xsl:for-each select="num">
<xsl:variable name="node" select="current()" />
<xsl:copy-of select="$node/accession" />
</xsl:for-each>
</root>
</xsl:template>
</xsl:transform>
Note that I used xsl:transform instead of xsl:stylesheet. Also, consider using version 2.0 instead of 1.0 if you have a compliant processor, it adds a lot of useful features.
I still don't see your need for a variable, though.