2011-11-14 40 views
9

Làm cách nào để tạo UUID bằng XSLT thuần túy? Về cơ bản tìm kiếm một cách để tạo ra các chuỗi duy nhất với XSLT. Trình tự có thể dài bất kỳ.XSLT tạo UUID

Tôi đang sử dụng XSLT 2.0.

+0

thể trùng lặp của [Tạo GUID trong XSLT] (http://stackoverflow.com/questions/5494175/generate-guid-in-xslt) –

Trả lời

1

Kể từ XSLT là một ngôn ngữ chức năng, tạo ra số ngẫu nhiên không phải là một phần của ngôn ngữ. Điều đó nói rằng, có các gói mở rộng (EXSLT) và một số bộ xử lý (Saxon) hỗ trợ việc tạo ra các số ngẫu nhiên. Nếu bạn không thể sử dụng tiện ích mở rộng hoặc Saxon, thì tôi tin rằng bạn không may mắn.

+2

Saxon hỗ trợ thế hệ số ngẫu nhiên như thế nào? – Ayyoudy

+0

Saxon đi kèm với mô-đun ngẫu nhiên EXSLT được tích hợp sẵn. Xem http://saxonica.com/documentation/extensions/intro.xml –

+0

Cảm ơn bạn. Quá xấu các mô-đun EXSLT được tích hợp sẵn không có sẵn cho Saxon HE (Home Edition). – Ayyoudy

10

Đây là số good example. Về cơ bản bạn thiết lập một phần mở rộng trỏ đến lớp UUID java, và sau đó tham khảo nó trong XSL:

<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:uuid="java:java.util.UUID"> 
<xsl:template match="/"> 
    <xsl:variable name="uid" select="uuid:randomUUID()"/> 
    <xsl:value-of select="$uid"/> 
</xsl:template> 
+0

Xin lỗi, vì không làm rõ. Tôi đã thấy ví dụ đó trước nhưng nó cần phải được thực hiện trong XSLT thuần túy. Không có Java. – Ayyoudy

+1

'xsl: value-of' không thể là con của' xsl: stylesheet' ... – Abel

+0

Tôi đã upvoted vì điều này làm việc cho tôi. Tuy nhiên, đáng chú ý là các cuộc gọi java phản xạ như thế này cũng không có sẵn cho các giấy phép Saxon HE (mặc dù như những người khác đã lưu ý, nó ít nhiều là một vấn đề được giải quyết để viết các chức năng của riêng bạn để làm điều đó). –

4

Hãy xem một câu hỏi khác Generate GUID in XSLT.

lẽ this bài viết sẽ giúp bạn - có chức năng XSLT được xác định để tạo ra GUID

2

Đối tạo số ngẫu nhiên trong XSLT, xem Casting the Dice with FXSL: Random Number Generation Functions in XSLT. Hàm mở rộng duy nhất mà nó sử dụng là nút-set(), không còn cần thiết trong XSLT 2.0 nữa.

Ngoài ra, nếu yêu cầu chỉ là các ID là duy nhất (không nhất thiết là ngẫu nhiên), hãy xem how to generate unique string. Ví dụ: nếu bạn đang tạo UUID cho từng phần tử của tài liệu XML đầu vào, bạn có thể sử dụng kết hợp URL của tài liệu đầu vào và <xsl:number> để tạo chuỗi duy nhất cho mỗi phần tử.

4

Bạn có thể sử dụng đoạn mã XSLT cho điều này (nguồn: http://code.google.com/p/public-contracts-ontology/source/browse/transformers/GB-notices/uuid.xslt?r=66e1d39a1c140079a86d219df5b3e031007cc957):

<xsl:stylesheet xmlns:uuid="http://www.uuid.org" xmlns:math="http://exslt.org/math" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

     <xsl:template match="/"> 
       <xsl:value-of select=" 
concat('First random ID:', uuid:get-id()), 
concat('Base timestamp: ', uuid:generate-timestamp()), 
concat('Clock id: ' ,uuid:generate-clock-id()), 
concat('Network node: ' ,uuid:get-network-node()), 
concat('UUID Version: ' ,uuid:get-uuid-version()), 
concat('Generated UUID: ' ,uuid:get-uuid()), 
concat('Generated UUID: ' ,uuid:get-uuid()), 
concat('Generated UUID: ' ,uuid:get-uuid()), 
concat('Generated UUID: ' ,uuid:get-uuid()) 
" separator="&#10;"/> 
     </xsl:template> 

    <!-- 
Functions in the uuid: namespace are used to calculate a UUID 
The method used is a derived timestamp method, which is explained 
here: http://www.famkruithof.net/guid-uuid-timebased.html 
and here: http://www.ietf.org/rfc/rfc4122.txt 
--> 
    <!-- 
Returns the UUID 
--> 
    <xsl:function name="uuid:get-uuid" as="xs:string*"> 
     <xsl:variable name="ts" select="uuid:ts-to-hex(uuid:generate-timestamp())"/> 
     <xsl:value-of separator="-" select=" 
      substring($ts, 8, 8), 
      substring($ts, 4, 4), 
      string-join((uuid:get-uuid-version(), substring($ts, 1, 3)), ''), 
      uuid:generate-clock-id(), 
      uuid:get-network-node()"/> 
    </xsl:function> 
    <!-- 
internal aux. fu 
with saxon, this creates a more-unique result with 
generate-id then when just using a variable containing a node 
--> 
    <xsl:function name="uuid:_get-node"> 
     <xsl:comment/> 
    </xsl:function> 
    <!-- generates some kind of unique id --> 
    <xsl:function name="uuid:get-id" as="xs:string"> 
     <xsl:sequence select="generate-id(uuid:_get-node())"/> 
    </xsl:function> 
    <!-- 
should return the next nr in sequence, but this can't be done 
in xslt. Instead, it returns a guaranteed unique number 
--> 
    <xsl:function name="uuid:next-nr" as="xs:integer"> 
     <xsl:variable name="node"> 
      <xsl:comment/> 
     </xsl:variable> 
     <xsl:sequence select=" 
      xs:integer(replace(
      generate-id($node), '\D', ''))"/> 
    </xsl:function> 
    <!-- internal fu for returning hex digits only --> 
    <xsl:function name="uuid:_hex-only" as="xs:string"> 
     <xsl:param name="string"/> 
     <xsl:param name="count"/> 
     <xsl:sequence select=" 
      substring(replace(
      $string, '[^0-9a-fA-F]', '') 
      , 1, $count)"/> 
    </xsl:function> 
    <!-- may as well be defined as returning the same seq each time --> 
    <xsl:variable name="_clock" select="uuid:get-id()"/> 
    <xsl:function name="uuid:generate-clock-id" as="xs:string"> 
     <xsl:sequence select="uuid:_hex-only($_clock, 4)"/> 
    </xsl:function> 
    <!-- 
returns the network node, this one is 'random', but must 
be the same within calls. The least-significant bit must be '1' 
when it is not a real MAC address (in this case it is set to '1') 
--> 
    <xsl:function name="uuid:get-network-node" as="xs:string"> 
     <xsl:sequence select="uuid:_hex-only('09-17-3F-13-E4-C5', 12)"/> 
    </xsl:function> 
    <!-- returns version, for timestamp uuids, this is "1" --> 
    <xsl:function name="uuid:get-uuid-version" as="xs:string"> 
     <xsl:sequence select="'1'"/> 
    </xsl:function> 
    <!-- 
Generates a timestamp of the amount of 100 nanosecond 
intervals from 15 October 1582, in UTC time. 
--> 
    <xsl:function name="uuid:generate-timestamp"> 
     <!-- 
date calculation automatically goes 
correct when you add the timezone information, in this 
case that is UTC. 
--> 
     <xsl:variable name="duration-from-1582" as="xs:dayTimeDuration"> 
      <xsl:sequence select=" 
       current-dateTime() - 
       xs:dateTime('1582-10-15T00:00:00.000Z')"/> 
     </xsl:variable> 
     <xsl:variable name="random-offset" as="xs:integer"> 
      <xsl:sequence select="uuid:next-nr() mod 10000"/> 
     </xsl:variable> 
     <!-- do the math to get the 100 nano second intervals --> 
     <xsl:sequence select=" 
      (days-from-duration($duration-from-1582) * 24 * 60 * 60 + 
      hours-from-duration($duration-from-1582) * 60 * 60 + 
      minutes-from-duration($duration-from-1582) * 60 + 
      seconds-from-duration($duration-from-1582)) * 1000 
      * 10000 + $random-offset"/> 
    </xsl:function> 
    <!-- simple non-generalized function to convert from timestamp to hex --> 
    <xsl:function name="uuid:ts-to-hex"> 
     <xsl:param name="dec-val"/> 
     <xsl:value-of separator="" select=" 
      for $i in 1 to 15 
      return (0 to 9, tokenize('A B C D E F', ' ')) 
      [ 
      $dec-val idiv 
      xs:integer(math:power(16, 15 - $i)) 
      mod 16 + 1 
      ]"/> 
    </xsl:function> 
    <xsl:function name="math:power"> 
     <xsl:param name="base"/> 
     <xsl:param name="power"/> 
     <xsl:choose> 
      <xsl:when test="$power &lt; 0 or contains(string($power), '.')"> 
       <xsl:message terminate="yes"> 

        The XSLT template math:power doesn't support negative or 

        fractional arguments. 

       </xsl:message> 
       <xsl:text>NaN</xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="math:_power"> 
        <xsl:with-param name="base" select="$base"/> 
        <xsl:with-param name="power" select="$power"/> 
        <xsl:with-param name="result" select="1"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:function> 
    <xsl:template name="math:_power"> 
     <xsl:param name="base"/> 
     <xsl:param name="power"/> 
     <xsl:param name="result"/> 
     <xsl:choose> 
      <xsl:when test="$power = 0"> 
       <xsl:value-of select="$result"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="math:_power"> 
        <xsl:with-param name="base" select="$base"/> 
        <xsl:with-param name="power" select="$power - 1"/> 
        <xsl:with-param name="result" select="$result * $base"/> 
       </xsl:call-template> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet>:choose> 
    </xsl:template> 
</xsl:stylesheet> 
+0

upvoted ... thank bạn :) – Ayyoudy

+0

Cảm ơn bạn đã chia sẻ. Nguồn (public-contract-ontology) là một liên kết chết: ( –

+0

Có thể nhận được 4 UUID khác nhau với mã này "": 23CD00A6-8952-11E6-2114-09173F13E4C5 23CD00A5-8952-11E6-2114-09173F13E4C5 23CD00A3-8952-11E6-2114-09173F13E4C5 23CD00A4-8952-11E6-2114-09173F13E4C5 –

0

Nếu sử dụng .Net 's XslCompiledTransform chuyển đổi XSL, bạn có thể thiết lập các EnableScripts tài sản để true, sau đó sử dụng mã như bên dưới :

<msxsl:script language="C#" implements-prefix="csharp"> 
    <![CDATA[ 
    public static string NewGuid() 
    { 
     return Guid.NewGuid().ToString(); 
    } 
    ]]> 
</msxsl:script> 

NB: Tôi đã cung cấp chức năng tùy chỉnh này tên/tiền tố csharp ở trên; nhưng bạn có thể gọi nó là bất cứ điều gì bạn thích.

Để biết thêm về cách bật tập lệnh, hãy xem https://stackoverflow.com/a/1873265/361842.

Full tập tin XSLT dưới đây để đưa ra một số bối cảnh bổ sung:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:csharp="urn:JohnLBevan/NewGuid" 
    exclude-result-prefixes="xsl msxsl csharp" 
> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="//*/text()"> 
     <!-- replaces all text nodes from input document with GUIDs --> 
     <xsl:value-of select="csharp:NewGuid()"/> 
    </xsl:template> 

    <msxsl:script language="C#" implements-prefix="csharp"> 
     <![CDATA[ 
     public static string NewGuid() 
     { 
      return Guid.NewGuid().ToString(); 
     } 
     ]]> 
    </msxsl:script> 

</xsl:stylesheet>