Getting wrong answer from a comparison XSL - xslt-1.0

So this is fairly simple I think, it could be more involved then I understand though.
Anyways, at the moment I'll just include the code I believe to be relevant, if someone thinks that more would be relevant then I will try to include more.
I've got two statements:
<xsl:value-of select="$isOnlineColumnEmpty" />
<xsl:value-of select="not($isOnlineColumnEmpty = 'false')" />
The first one outputs false. However, the second one is outputting true, which is the opposite of what I expect.
In addition to this, These two statements get repeated multiple times, and I only get this result in one section. However, there is absolutely no code in between these two statements, so nothing could be changing the value of the variable.
Just wondering if there is something I could be overlooking?

Instead of:
<xsl:value-of select="not($isOnlineColumnEmpty = 'false')" />
use:
<xsl:value-of select="not($isOnlineColumnEmpty = false())" />
Explanation:
The boolean value false() is something different from the string "false".
When a boolean is compared to another value, the second value is converted to a boolean and then the comparisson is performed. To quote the XPath 1.0 W3C Specification:
"If at least one object to be compared is a boolean, then each object
to be compared is converted to a boolean as if by applying the boolean
function."
So, in this concrete case the string "false" is converted to boolean. By definition boolean($someString) is true() for any non-empty string.
Therefore, after the conversion the two boolean values false() and true() are compared and the result is false(). Because in the original expression this result is argument to the not() function, the final result is not(false()) , that is true().
Here is the chain of calculations:
not($isOnlineColumnEmpty = 'false') ==> not(false() = 'false') ==>
not(false() = boolean(false())) ==> not(false() = true()) ==>
not(false()) ==> true()

So, I figured this out later.
Changing the statement to:
<xsl:value-of select="$isOnlineColumnEmpty != false" />
Fixed the issue for me.

Related

Difference between sequential and combined predicates

In Selenium I have written a xpath and both of them retrieves the same result.
//a[#role='tab'][text()=' Assets']
//a[#role='tab' and text()=' Assets']
Does both of them have the same meaning?
In most cases a[b][c] has exactly the same effect as a[b and c]. There are two exceptions to be aware of:
They are not equivalent if either predicate is numeric, or has a dependency on position() or last() (I call these positional predicates). For example a[#x][1] selects the first a element that has an #x attribute, while a[1][#x] selects the first a element provided it has an #x attribute (and selects nothing otherwise). By contrast a[1 and #x] converts the integer 1 to the boolean true(), so it just means a[#x].
There may be differences in behaviour if evaluation of b or c fails with a dynamic error. The precise rules here depend on which version of XPath you are using, and to be honest the rules leave implementations some leeway, but you need to exercise care if you want to be sure that in the event of b being false, c is not evaluated. (This hardly matters in XPath 1.0 because very few expressions throw dynamic errors.)
When you add Square Brackets ([]) to XPath you are adding a condition, so
first row adding 2 conditions
Which produce similar results as adding condition with and
Normally you don't use first row, because it less readable,
Mainly because this syntax represent in other languages a Matrix
// return a random m-by-n matrix with values between 0 and 1
public static double[][] random(int m, int n) {
See tutorial:
5 XPaths with predicates
A predicate is an expression that can be true or false
It is appended within [...] to a given location path and will refine results
More than one predicate can be appended to and within (!) a location path
The first one is a predicate, which means it checks if a[#role='tab'] is true then it proceeds to [text()=' Assets']
The second one is a just using an and operator so it validates both are true.

CType being evaluated before the rest of expression

I'm trying to write the return statement of my function like this
Return (Not IsDbNull(result)) And (CType(result, String) = "1")
However, when result is DbNull, it throws me an InvalidCastException
Writing (Not IsDbNull(result)) And 2/0 = 1 in my watch works so it seems to me like the CType function has something special that makes it be evaluated before the rest of expression.
am I seeing things or CType doesn't respect the evaluation order in VB.NET? Is there a way around this problem that doesn't involve splitting my expression into several parts and assigning them into variables?
You should almost always use AndAlso instead of And (and OrElse instead of Or).
A logical operation is said to be short-circuiting if the compiled
code can bypass the evaluation of one expression depending on the
result of another expression. If the result of the first expression
evaluated determines the final result of the operation, there is no
need to evaluate the second expression
And on the other hand will evaluate both expression which causes this exception:
In a Boolean comparison, the And operator always evaluates both
expressions
You could also use Convert.ToString that treats Nothing or DbNull as empty string:
Return Convert.ToString(result) = "1"
In your case - converting to string - you don't need DbNull checking and converting to string.
Code below will be enough.
Return result.ToString().Equals("1")
Because DbNull.ToString() returns empty string.
In case result returned by ExecuteScalar - where Nothing(null) value is possible, as pointed out by Tim Schmelter, you can add validation for null
Dim checkedResult = If(result, String.Empty)
Return checkedResult.ToString().Equals("1")
Or use static Object.Equals method
Return Equals(result, "1")
If result is item of DataRow type then suggest using extension method for converting values to the proper type
Dim value As Integer = datarow.Field(Of Integer)("IntegerColumnName")
Dim value As String = datarow.Field(Of String)("StringColumnName")
DataRow will return empty string if value is DbNull

Using concat with number values

The problem is I want to present two numbers that are stored as strings nicely in a file I generate.
The following code works just fine, but the formatting is not really the one I would like it to be:
<xsl:call-template name="create-cell">
<xsl:with-param name="value" select="concat($value_one,' or ',$value_two)" />
So I thought that I'll add a format-number function and give the numbers the format I want them to have. In order to do so I cast the string to number, use the function and then cast back to string, like this:
<xsl:call-template name="create-cell">
<xsl:with-param name="value" select="concat(string(format-number(number($value_one), "###,###.00"),' or ',$value_two)" />
But the transformation ends without results (an error occurs). What exactly am I doing wrong when changing the type?
EDIT:
The error that occurs is:
Element type "xsl:with-param" must be followed by either attribute specifications, ">" or "/>"
I guess the solution is to escape the double quotas with &quot ...
This part :
<xsl:with-param name="value" select="concat(string(format-number(number($value_one), "###,###.00"),' or ',$value_two)" />
should be written as:
<xsl:with-param name="value" select="concat(format-number($value_one, '#,###.00'), ' or ', $value_two)"/>
Whether that's a good approach to solve the actual problem (of which we know practically nothing) is another question.
But the transformation ends with result -
My guess is that $value_one is not a number. Perhaps it is formatted as 12,345.00? If the conversion to an xs:double fails, it will return NaN, which is a valid number, but not really. Using the format-number function, it should return NaN, regardless the picture string.
If your variable holds the empty sequence, format-number will return the empty sequence.
Since format-number already returns a string, using string() on the result will have no effect.
If the - in your question meant a literal minus-sign, then perhaps update your question with what your first snippet and second snippet return exactly, and what processor (exact version) you use.
Update (after you posted the error)
Your XSLT is not valid XML. All XSLT must be valid XML to begin with. Michael's answer shows where it goes wrong: an attribute value must be enclosed in quotes, and yours wasn't.

Regex match SQL values string with multiple rows and same number of columns

I tried to match the sql values string (0),(5),(12),... or (0,11),(122,33),(4,51),... or (0,121,12),(31,4,5),(26,227,38),... and so on with the regular expression
\(\s*\d+\s*(\s*,\s*\d+\s*)*\)(\s*,\s*\(\s*\d+\s*(\s*,\s*\d+\s*)*\))*
and it works. But...
How can I ensure that the regex does not match a values string like (0,12),(1,2,3),(56,7) with different number of columns?
Thanks in advance...
As i mentioned in comment to the question, the best way to check if input string is valid: contains the same count of numbers between brackets, is to use client side programm, but not clear SQL.
Implementation:
List<string> s = new List<string>(){
"(0),(5),(12)", "(0,11),(122,33),(4,51)",
"(0,121,12),(31,4,5),(26,227,38)","(0,12),(1,2,3),(56,7)"};
var qry = s.Select(a=>new
{
orig = a,
newst = a.Split(new string[]{"),(", "(", ")"},
StringSplitOptions.RemoveEmptyEntries)
})
.Select(a=>new
{
orig = a.orig,
isValid = (a.newst
.Sum(b=>b.Split(new char[]{','},
StringSplitOptions.RemoveEmptyEntries).Count()) %
a.newst.Count()) ==0
});
Result:
orig isValid
(0),(5),(12) True
(0,11),(122,33),(4,51) True
(0,121,12),(31,4,5),(26,227,38) True
(0,12),(1,2,3),(56,7) False
Note: The second Select statement gets the modulo of sum of comma instances and the count of items in string array returned by Split function. If the result isn't equal to zero, it means that input string is invalid.
I strongly believe there's a simplest way to achieve that, but - at this moment - i don't know how ;)
:(
Unless you add some more constraints, I don't think you can solve this problem only with regular expressions.
It isn't able to solve all of your string problems, just as it cannot be used to check that the opening and closing of brackets (like "((())()(()(())))") is invalid. That's a more complicated issue.
That's what I learnt in class :P If someone knows a way then that'd be sweet!
I'm sorry, I spent a bit of time looking into how we could turn this string into an array and do more work to it with SQL but built in functionality is lacking and the solution would end up being very hacky.
I'd recommend trying to handle this situation differently as large scale string computation isn't the best way to go if your database is to gradually fill up.
A combination of client and serverside validation can be used to help prevent bad data (like the ones with more numbers) from getting into the database.
If you need to keep those numbers then you could rework your schema to include some metadata which you can use in your queries, like how many numbers there are and whether it all matches nicely. This information can be computed inexpensively from your server and provided to the database.
Good luck!

Convert an alphanumeric string to integer format

I need to store an alphanumeric string in an integer column on one of my models.
I have tried:
#result.each do |i|
hex_id = []
i["id"].split(//).each{|c| hex_id.push(c.hex)}
hex_id = hex_id.join
...
Model.create(:origin_id => hex_id)
...
end
When I run this in the console using puts hex_id in place of the create line, it returns the correct values, however the above code results in the origin_id being set to "2147483647" for every instance. An example string input is "t6gnk3pp86gg4sboh5oin5vr40" so that doesn't make any sense to me.
Can anyone tell me what is going wrong here or suggest a better way to store a string like the aforementioned example as a unique integer?
Thanks.
Answering by request form OP
It seems that the hex_id.join operation does not concatenate strings in this case but instead sums or performs binary complement of the hex values. The issue could also be that hex_id is an array of hex-es rather than a string, or char array. Nevertheless, what seems to happen is reaching the maximum positive value for the integer type 2147483647. Still, I was unable to find any documented effects on array.join applied on a hex array, it appears it is not concatenation of the elements.
On the other hand, the desired result 060003008600401100500050040 is too large to be recorded as an integer either. A better approach would be to keep it as a string, or use different algorithm for producing a number form the original string. Perhaps aggregating the hex values by an arithmetic operation will do better than join ?