I have a xsl template with the code
<xsl:if test="(base_extra_fee_rule_amount='75.0000')">
But I want the code to run if there any value for that field or don't run the code if the field is NaN
I tried varations of
<xsl:if test="not(base_extra_fee_rule_amount='NaN')">
But that doesn't work, is there a simple way of achieving this?
The simplest way to test whether X is NaN is (X=X), because only if X is NaN will that expression return false.
If you want a more readable expression, then string(number(X))='NaN' does the job.
Note, however, the operand base_extra_fee_rule_amount returns either an element node or nothing. Only a value of type number can be NaN, so an element isn't going to be NaN until you try to convert it to a number. That can happen explicitly or implicitly, and the details depend on whether you're using XSLT 1.0 or 2.0, and in the latter case on whether it's schema-aware. At this stage it's not clear entirely what test you want to apply. Are you interested in testing whether the element has the string value "NaN", or are you interested in testing whether it has a value that is not a number?
Not sure what your purpose is here.
In general, you can select/match nodes with valid numeric values using a predicate - for example:
<xsl:template match="amount[number()=number()]">
PaddyD:-
Thanks for notified:-
<xsl:template match="base_extra_fee_rule_amount!=''"> <xsl:text>####</xsl:text> </xsl:template>
Related
I'm starting to learn XSLT/XPath, and I copied the following from a study guide, making some modifications:
<xsl:variable name="fname" select="'polist.xml'"/>
<xsl:variable name="thePath" select="'/collection/doc'"/>
...
<xsl:value-of select="count(doc($fname)/collection/doc)"/>
It reports the number of doc elements in the XML file. The doc() function accepts the file name variable 'fname'. But if I try to do the same with the 'thePath' variable in the count() function, using $thePath instead of the "/collection/doc" text, I get an error.
Suggestions on whether/how to use the 'thePath' variable in the count() function? Is it possible? Thanks!
Learning from examples leaves you very exposed to this kind of problem: it's easy to build a completely incorrect mental model of how the examples actually work. That's why I always advise people to start by reading a good book that explains the concepts first.
In your case you've made a common mistake, which is to assume that variables work like macros, that is, that they represent fragments of XPath text that can be substituted into an expression. That's not the case: variables represent values, the result of evaluating an expression, and you can only use a variable in places where a literal value (like a number or string) could appear.
(I suspect it's the use of the $ sign that leads to this false impression. $ is often used to represent variables in macro-like languages, for example shell scripts).
In XPath 1.0 there's no direct way of achieving what you are trying to do. In practice people either use vendor extensions for this, or they construct a pipeline in which phase 1 generates an XSLT stylesheet and phase 2 executes it (that's easier in XSLT than in most other languages, because XSLT is XML and can therefore be easily manipulated using XSLT).
In 3.0 you can evaluate XPath expressions supplied in the form of a string using the xsl:evaluate instruction. But very often, the requirement can be met better using functions. We don't know what the real underlying requirement is here so it's hard to know whether that's true in this case.
An example use of xsl:evaluate in XSLT 3 would be e.g.
<xsl:evaluate xpath="'count(' || $thePath || ')'" context-item="doc($fname)"/>
I want to validate an assumption that a set of 'or' statements as a predicate of a for-each operates analogous to the choose statement. Either things work as I expect or I just haven't hit the edge case that will cause an issue.
In a choose structure I know that it is evaluated in sequence and when the sequence finds a test that resolves to 'true' the processor drops out of the choose.
<xsl:choose>
<xsl:when test="number($A) and $A=1">
<!—do a thing -->
</xsl:when>
<xsl:when test="number($A) and $A=2">
<!—do a thing -->
</xsl:when>
<xsl:when test="number($A) and $A < 3">
<!—do a thing -->
</xsl:when>
</xsl:choose>
So if the first and third when is true (highly probable), the processor drops out of the choose when the first when resolves as true. This is great and expected. However, when this choose needs to be compressed into a for-each it seems a simple task, but a nagging thought in my mind is that I'm just getting lucky.
<xsl:for-each select="bunch of paths[(number($A) and $A=1) or (number($A) and $A=2) or (number($A) and $A < 3)]
In this example whether the first or third (or both) passes probably doesn't matter, but most of my work operates on financial dates so in that respect I want to be sure that if the first and third both pass that the predicate will evaluate the same as the choose statement.
So, I'm just seeking to ensure that my assumption that has been based on observation of predicate evaluation within the for-each is the same as the choose.
A significant difference between the two cases is that with the xsl:for-each example the evaluation context changes (both in the predicate, and in the body of the for-each instruction), while in the xsl:choose case, the context is the same throughout.
Another difference is that xsl:when always takes the effective boolean value of the test expression (so number 1 means true), whereas predicates have different semantics if the value is numeric.
Usually the programming languages allow you to declare a variable for example:
Dim test as integer <-- Visual Basic
and subsequently allow to increase the value in a for each cycle.
for test=0 to 3
print test
next
Can I create a similar structure in XSLT 1.0?
With 'xsl:variable', I declare a variable, but if I want to increase in a for-each as you do?
The closest is XSLT 2.0 with
<xsl:for-each select="0 to 3">
<xsl:value-of select="."/>
</xsl:for-each>
which processes the sequence of integers 0, 1, 2, 3.
As you see, it does not use a variable and increments that, as variables are immutable, you simply bind a value to them once.
With XSLT 1.0 you can process nodes or you can write a recursive, named templates where each recursive call passes on an incremented parameter value. Whether you actually need that depends on your requirements, if you are new to the declarative programming of XSLT then it is best that you define your problem by showing a sample of the XML input and the corresponding output you want to create, explaining how the input is mapped to the output.
<xsl:when test="person/id!=127 or 112" >
or condition is not working in the above example. Please help
You've got your syntax wrong, and it should be an and, not or. Try this:
<xsl:when test="person/id!=127 and person/id!=112" >
If you put an or there, your condition is going to be true no matter what the value of ID is, because no number can equal 127 and 112 at the same time.
Try
<xsl:when test="person/id!=127 and person/id!=112">
Use:
not(person/id= 127 or person/id = 112)
Try to always avoid the != XPath operator, due to its unintuitive (and rarely useful) semantics when one or both of its arguments are node-sets 9or sequences in XPath 2.0).
When you have a long list to compare against, this kind of expression may be more convenient and efficient:
not(contains('|101|105|108|112|123|127|', concat('|', person/id, '|'))
I am not an xslt developer and never used it before. However, It appears that test statement is missing. what should xslt parser do with 112? no condition is provided for it.
<xsl:value-of select="$MyVar"/>
works but
<xsl:value-of select="MyDataPfath/$MyVar"/>
do not work.
What is wrong in my code?
From the look of it, what you are trying to achieve is 'dynamic evaluation'. XSLT does not support the dynamic evaluation of XPath by default, so you will need to make use of an extension function.
Depending on your XSLT processor, you might want to look at EXSLT extensions. In particular the dynamic module at http://www.exslt.org/dyn/index.html. This would allow to do something like this
<xsl:value-of select="dyn:evaluate('MyDataPfath/$MyVar')"/>
However, in your case, perhaps the $MyVar contains just a single element name. In which case you could change your command to the following, which would work without any extension functions
<xsl:value-of select="MyDataPfath/*[local-name() = $MyVar]"/>
Your code didn't fail, it did exactly what the specification says it should do. Which was different from what you were hoping/imagining that it might do.
Your hopes/imagination were based on a fundamental misunderstanding of the nature of variables in XPath. XPath variables are not macros. They don't work by textual substitution; they represent values. If the variable $E contains the string "X", then MyPath/$E means the same as MyPath/"X", which is illegal in XPath 1.0, and in XPath 2.0 returns as many instances of the string "X" as there are nodes in MyPath.
You probably intended MyPath/*[name()=$E]
it is not possible to get the value by using syntax 'MyDataPfath/$MyVar' in . it will not recognize the proper path.
suppose $MyVar has value 'Hi'. so it will be represented as 'MyDataPfath/"Hi"', this is not valid path, which you want to retrieve from the XML.
to remove this limitation, You can use name() or local-name() function, that can be used as follows:
or