0

I have a requirement wherein I need to generate a 32-character random string value using XSLT containing upper case letters, lower case letters & numbers.

I am using the below code for this right now, however, the values generated are too similar and upper case letters are not included.

Is there an alternate way to achieve this?

    <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" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="node()">
      <xsl:apply-templates/>
  </xsl:template>

<xsl:template match="/">

<ABC>
<xsl:for-each select="ABC/ABC">
<DEF>
 
<externalCode><xsl:value-of select="concat(generate-id(),generate-id(),generate-id(),generate-id())"/></externalCode>
<userId><xsl:value-of select="userId"/></userId>

</DEF> 
</xsl:for-each>
</ABC> 

</xsl:template>
</xsl:stylesheet>

Thanks

megrao1811
  • 21
  • 2
  • There is no random function in XSLT 1.0. Which processor are you using? You may be able to utilize some extension it supports. Otherwise you will need to supply at least a seed (a random value or a current timestamp) as a parameter when calling the transformation. – michael.hor257k Feb 14 '23 at 13:47
  • The use of `xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"` is a bit unusual for XSLT 1.0. Are you sure you are not using an XSLT 3 processor like Saxon 10 or later or Altova 2017 R2 and later where you could use `random-number-generator()` and its `permute` function? – Martin Honnen Feb 14 '23 at 14:53
  • With XSLT questions, please tag the question with a specific XSLT version, as the answer will often be version-dependent. – Michael Kay Feb 14 '23 at 17:23

2 Answers2

2

XSLT has a random-number-generator() function returning a map with a permute function to return an input sequence in random order so given that your requirement is 32 characters taken from a sequence of all letters in lower case and upper case and digits (which are much more than 32) it will probably suffice to call e.g.

string-join((random-number-generator(current-dateTime())?permute($symbol-seq))[position() le 32], '')

As the other answer uses Python anyway, SaxonC HE 12 is now available as a PyPi package so you can do it all in XSLT 3 but if wanted/needed run from Python:

from saxonche import *

xslt = '''<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">
  
  <xsl:param name="symbols" as="xs:string" expand-text="no">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</xsl:param>
  
  <xsl:variable name="symbol-seq" as="xs:string*" select="($symbols => string-to-codepoints()) ! codepoints-to-string(.)"/>

  <xsl:template name="xsl:initial-template">
    <test>{string-join((random-number-generator(current-dateTime())?permute($symbol-seq))[position() le 32], '')}</test>
  </xsl:template>
  
</xsl:stylesheet>'''

with PySaxonProcessor(license=False) as proc:
    print(proc.version)

    xslt30_processor = proc.new_xslt30_processor()

    xslt30_transformer = xslt30_processor.compile_stylesheet(stylesheet_text=xslt)

    if xslt30_processor.exception_occurred:
        print(xslt30_processor.error_message)
    else:
        result = xslt30_transformer.call_template_returning_string()

        print(result)

Result output is e.g.

SaxonC-HE 12.0 from Saxonica
<?xml version="1.0" encoding="UTF-8"?><test>OQKMahpLesBCI3lUuGR6jEYf1yqZiWJw</test>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

One possibility might be to generate the 32 character random string external to the XSLT processing and pass that generated value as a --stringparam to your XSLT transform.

Here is a python3 implementation for generating a random 32 character string with uppercase, lowercase, and digits:

python3 -c "import string,random; print(''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits, k=32)))"

Sample output: 4Ve3o1oURX3oVzn5954SnVLlqviWp9uN


Using the above implementation as part of an XSLT transform:

xsltproc --stringparam random $(python3 -c "import string,random; print(''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits, k=32)))") p.xslt p.xml

XSLT output:

<externalCode>m4lrO26bujNjS1FopZ7jv31Di1zK7xdP</externalCode>

Contents of p.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:template match="/">
      <externalCode>
      <xsl:value-of select="$random"/>
      </externalCode>
  </xsl:template>

</xsl:stylesheet>

Contents of p.xml:

<data>
  dummy_xml
</data>
j_b
  • 1,975
  • 3
  • 8
  • 14