1

I would like to concatenate some random number into date. Generally it looks like that:

http://xsltransform.net/bdxtrc/1

The result should be eg 2015-09-08T13:53:41.514Z54321 Where 54321 is a random number.

I tried to use EXSLT - RANDOM:RANDOM-SEQUENCE function but it doesn't work correctly. I dont know why. Could anyone help me? Thanks, Regards

andreww
  • 223
  • 6
  • 16
  • Hi again ;). You are not calling the function, but you are using a nametest. However, after I changed it to `random:random-sequence(10, 12.0)[1]`, it still threw an error, saying that the function did not exist. Have you looked at this? http://stackoverflow.com/questions/2359134/random-items-in-xslt – Abel Sep 08 '15 at 14:11
  • OMG, is it really so hard to generate simple random numbers:D not good – andreww Sep 08 '15 at 14:22
  • Random numbers are never simple, it is actually very hard in any language, but it is particularly hard in a _functional language_ (see for why this is: http://programmers.stackexchange.com/questions/202908/how-do-functional-languages-handle-random-numbers). In XPath 3.1, the omission of a standard function was fixed. But what is hard with the code above? The function returns a set of numbers. You need to say which one you need. Any random number generator requires a seed (the 2nd argument) and an amount (the first argument). Nothing different from other languages there. – Abel Sep 08 '15 at 14:27
  • XSLT and XPath, but also F#, Haskell, Erlang, are _pure functional languages_. That means: twice the same function call to the same function will result in the same result. Hence the problem with random numbers. You need a way to change the argument (in my example below, I do that by using the current position). This is true for any functional language and is the core reason why they are so stable and never (hardly ever) have `NullPointerExceptions`, and code you write "just works" and can easily be multi-threaded. But of course, there is a learning curve as with any language ;). – Abel Sep 08 '15 at 14:33
  • 2
    @maciek2791 "*is it really so hard to generate simple random numbers*" It's easier than getting you to answer the question: which XSLT processor are you using? – michael.hor257k Sep 08 '15 at 14:43

2 Answers2

1

Ok, I tried it locally using oXygen, which comes with a built-in version of Saxon-EE. It looks like that site disabled extension functions, probably for security reasons (some can be dangerous). That is why you receive:

XTDE1425: Cannot find a matching 2-argument function named
  {http://exslt.org/random}random-sequence(). There is no Saxon extension function with the
  local name random-sequence

This error can also come from using a free version of Saxon, from a recent question I asked Michael Kay about it, he answered (full quote):

The general policy is that Saxon-HE supports the basic conformance levels of published recommendations: For Saxon 9.6 this means XPath 3.0 and XQuery 3.0 but not XSLT 3.0, and not XPath 3.1, and not optional features such as higher-order functions.

Extensions, including Saxon extensions as well as EXSLT and EXPath extensions, generally require Saxon-PE or higher.

In a follow-up he explains how you can use integrated extension functions created by yourself. This is true for the online version (where EE doesn't work) and possibly for your local version, unless you use PE or higher. If you get this error locally as well, upgrade Saxon, or use an alternative method (see bottom).

The following works, which will return the first item from the random sequence

random:random-sequence(10, 5987)[1]

Since you probably want a different number each time the correlationId is matched, you can change this as follows:

<xsl:variable name="pos" select="position()" />
<xsl:value-of 
   select="concat(current-dateTime(), random:random-sequence(100, 5987)[$pos])" />

Note, you do not need to use concat in XSLT 2.0 with xsl:value-of, the same can be written as:

<xsl:value-of 
   select="current-dateTime(), random:random-sequence(100, 5987)[$pos]"
   separator="" />

Note, your original code used:

<xsl:value-of select="concat(current-dateTime(),random:random-sequence)" />

This is nodetest (i.e. will return the value that is in the node random:random-sequence). If you call a function, you must use parentheses, or the function will not be called. And in this case, the function needs two arguments, which you need to pass, and returns a sequence of numbers.

I have created a new code snippet here: http://xsltransform.net/3NzcBue (please do not update it, so that it can remain with this answer, create a new snippet if you need to).


Edit: from the comments.

If the requirement is to have a unique string which only needs to vary based on the current node and does not have to be globally unique or anything, the XSLT way of doing this is to use the generate-id() function, which returns a guaranteed unique string within one execution of a stylesheet. If you add that to the current date-time, you will have a locally unique string.

XSLT 2.0, without extension functions:

<xsl:value-of select="concat(current-dateTime(), generate-id(.))" />
Community
  • 1
  • 1
Abel
  • 56,041
  • 24
  • 146
  • 247
  • Abel, you are the best! : ) I put that code and thats the result: http://xsltransform.net/bdxtrc/2 . Am I doing smth wrong? – andreww Sep 08 '15 at 14:35
  • @maciek2791 I think you missed my opening para, please check that, it explains why it does not work. Have you already downloaded Saxon? – Abel Sep 08 '15 at 14:38
  • Could you explain which exactly "para"? Currently i'm using xlstransform website where i choose saxon engine. EDIT. Ok i see :) – andreww Sep 08 '15 at 14:46
  • Unfortanely i run it localy. Still doesn't work : (. Result is – andreww Sep 08 '15 at 14:57
  • Abel could you paste your xslt code? You said it is working on your computer. Maybe i did some mistakes in syntax etc – andreww Sep 08 '15 at 15:05
  • @maciek2791, I meant the first para in my answer (para == paragraph). You run it with an XSLT 2.0 processor like Saxon? As the result you give is then not possible. – Abel Sep 08 '15 at 15:05
  • Ok, the question is if it possible to generate random numbers with an XSLT 1.0? – andreww Sep 08 '15 at 15:08
  • @maciek, XSLT 1.0??? No, unless you have a processor that supports those extension functions. XSLT 1.0 is _very limited_ and >16 years old, which is an era in computing. If you want your stylesheets to run in the browser (tricky), you'll have to, if not, choose your freedom. In the browser, extensibiity is even more limited. However, a simple way is to use scripting with your own random function, which is supported by most XSLT 1.0 processor (check documentation), but usually not in the browser. I have updated the code, this works: http://xsltransform.net/3NzcBue (but not in that online tool). – Abel Sep 08 '15 at 15:14
  • @maciek2791, ok "no" is perhaps too strong. It is possible in pure XSLT 1.0, but if you can avoid it, do so. Use `generate-id()`, which will return a unique string for each node, in most cases this is more than enough "randomness", i.e. to generate unique idrefs in a HTML document. – Abel Sep 08 '15 at 15:16
  • Abel, thanks a lot for your help. I will try to do that tomorrow ;) – andreww Sep 08 '15 at 19:12
  • 1
    Hello again. I added: select="concat(current-dateTime(), generate-id())" , Generate some unique string is enough for me :) Abel once again - thanks for you help. Regards – andreww Sep 09 '15 at 06:44
  • @maciek2791, Good to hear that, I should have asked better about your requirements (why use an ext. function if something simpler suffices). For in the future, let us know (apart form using xsltransform.net) what processor you use locally, as it can greatly influence the answers. – Abel Sep 09 '15 at 06:48
  • Like a said I'm newbie so i had no idea which processor I'm using :D Abel, Now when i check that function (generate_id) -it seems that it is not exactly what I wanted. I thought that every time i run the transofmration I will get unique string. I need to upload the data from xml into database - thats why every record has to be unique. – andreww Sep 09 '15 at 06:53
  • @maciek2791 But do you know it now? Because we still dont :(. No, that is not what I said about it, quote: _"which returns a guaranteed unique string within one execution"_. Rerun your transformation and it will be unique. If you need to upload stuff to a database, use an auto-generated ID field in the database instead. For databases, and for XSLT, you can only make something unique if there is a unique attribute. If your data is equal and the nodes are equal (position, document), and the time is equal (same execution) then outcome of same functions will be equal. – Abel Sep 09 '15 at 06:57
  • It should be working just like "select="uuid:randomUUID()"/> " - it generates random string every time I run the code. But again it is only for Xalan processor : / – andreww Sep 09 '15 at 06:59
  • @maciek2791 No, it won't, because there is no argument, so the processor is allowed to evaluate only once. Unless the implementation of the function creates new nodes (this is an exception), but even then, it may return the same... Tricky, I know. The easy thing is to make the function dependent on the current node, like generate-id, but you said that didn't work, even though that is guaranteed unique. So I am at the loss as to how more uniqueness you want... (good to know you use Xalan). – Abel Sep 09 '15 at 07:02
  • I'm using Saxon processor :). I'm using generate-id(). Date is changing, but generate_id has still same value. I tried to do smth like generate-id(Current-dateTime) but of course it doesn't work :) – andreww Sep 09 '15 at 07:05
  • It's working : ) To early for me. Once again thanks for help. Promise i won't ask you again about nothing :D ( only this topic: :D ). – andreww Sep 09 '15 at 07:09
  • @maciek2791 _"Date is changing, but generate_id has still same value. "_ >>> If date changes, and generate-id is the same between runs (but different for each node), then this is correct, this is called _stable behavior_ of the function. That is because the XML document did not change. If you add a node at the beginning, you will see different ID's. To get a universally unique ID, combine generate-id with timestamp's milliseconds. – Abel Sep 09 '15 at 07:09
  • "*It should be working just like "select="uuid:randomUUID()"/> " ... But again it is only for Xalan processor*" No, it works with Saxon, too. – michael.hor257k Sep 09 '15 at 07:58
  • @michael.hor257k, not sure, it does not have that function. Unless you mean by using a Java extension function? Because out of the box I don't see support for UUID. – Abel Sep 09 '15 at 08:01
  • @Abel, Yes, of course I mean a Java extension. This is all a follow-up on the link in my answer, I believe. – michael.hor257k Sep 09 '15 at 08:04
  • @michael.hor257k, omg, sorry, didn't realize that! So the clutter here was part due to your answer ;) – Abel Sep 09 '15 at 08:10
  • @Abel Right. It's all my fault. – michael.hor257k Sep 09 '15 at 08:14
  • @michael.hor257k yep, sure:D. Fwiw, this whole discussion reminds me of a mail i sent on [GUID-generation in pure XSLT](http://markmail.org/message/4zxb654yeaf5twnv), using the new-node semantics. Haven't looked at it for ages... – Abel Sep 09 '15 at 08:24
1

I tried to use EXSLT - RANDOM:RANDOM-SEQUENCE function but it doesn't work correctly. I dont know why.

The most likely reason is that your processor doesn't support this function. To tell for certain, we would have to know what exactly "doesn't work correctly" and/or which XSLT processor you are using (something you refuse to tell us despite being asked several times, both here and in your previous question).

Still, I don't know of any XSLT 1.0 processor that supports the EXSLT random:random-sequence() function. OTOH, the EXSLT math:random() function is supported by libxslt, Xalan and Saxon 6 (to name just a few).

If your mysterious processor doesn't support it, see alternatives here: generate random number in RSS viewer webpart

See also: How to generate random UUID using xslt

Community
  • 1
  • 1
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • In the long thread, the mystique was resolved: (s)he uses Saxon. About `math:random`, this is supported by Saxon with a caveat: [it gets inlined and then returns the same](http://www.saxonica.com/html/documentation/functions/exslt-math/random.html) on each call. [`random:random-sequence` is also supported by Saxon](http://www.saxonica.com/html/documentation/functions/exslt-random/random-sequence.html) (I tested it with EE, it works). But possibly not on personal editions (hence the error of the OP). – Abel Sep 09 '15 at 07:57
  • @Abel The mystique is not resolved until we know the version, too. I vaguely recall Michael Kay saying in one of the comments that EXSLT support in the 9 series is limited to the paid versions. But I could be easily wrong about this. – michael.hor257k Sep 09 '15 at 08:02
  • I sent Michael Kay a message and a [prompt response showed your assumptions were correct](http://saxon.markmail.org/search/?q=#query:+page:1+mid:zuk3hh2etjihuqik+state:results). – Abel Sep 10 '15 at 06:50