如何生成唯一的字符串

时间:2010-12-22 13:33:49

标签: xslt

我想将XML文档转换为HTML。某些XML元素具有指向其他文档的链接,如:

<link href="1.html">

在HTML输出中,我想得到:

<a href="1.html&no_cache={unique_id}">

如何生成这个独特的相当大的ID?

4 个答案:

答案 0 :(得分:5)

首先,我假设由于某些未知原因,您无法使用link中的绝对URL作为所需的UID - 这是最简单,最自然的解决方案。

如果我的假设是正确的,那么:

对于XSLT来说,这是一项简单的任务

由于OP希望在多次执行转换时生成的id相同,因此使用generate-id()函数是不合适的。

以下是生成稳定ID的一种简单方法

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="link[@href]">
  <xsl:variable name="vUid">
    <xsl:number level="any" count="link[@href]"/>
  </xsl:variable>
   <a href="{@href}&amp;no_cache={{{$vUid}}}"/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档(无论多少次):

<t>
 <link href="1.html"/>
 <a>
   <link href="2.html"/>
  <b>
    <link href="3.html"/>
    <c>
     <link href="4.html"/>
    </c>
    <link href="5.html"/>
  </b>
  <link href="6.html"/>
  <d>
   <link href="7.html"/>
  </d>
 </a>
 <link href="8.html"/>
 <e>
  <link href="9.html"/>
 </e>
 <link href="10.html"/>
</t>

每次产生想要的,相同的,正确的结果

<t>
   <a href="1.html&amp;no_cache={1}"/>
   <a>
      <a href="2.html&amp;no_cache={2}"/>
      <b>
         <a href="3.html&amp;no_cache={3}"/>
         <c>
            <a href="4.html&amp;no_cache={4}"/>
         </c>
         <a href="5.html&amp;no_cache={5}"/>
      </b>
      <a href="6.html&amp;no_cache={6}"/>
      <d>
         <a href="7.html&amp;no_cache={7}"/>
      </d>
   </a>
   <a href="8.html&amp;no_cache={8}"/>
   <e>
      <a href="9.html&amp;no_cache={9}"/>
   </e>
   <a href="10.html&amp;no_cache={10}"/>
</t>

请注意:使用<xsl:number>来生成ID。

如果文档中多次出现相同的链接,我们需要所有出现的内容都使用相同的ID,这里是解决此问题的方法

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kHrefByVal" match="link/@href" use="."/>

 <xsl:variable name="vUniqHrefs" select=
  "//link/@href
       [generate-id()
       =
        generate-id(key('kHrefByVal',.)[1])
       ]
  "/>


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

 <xsl:template match="link[@href]">
  <xsl:variable name="vthisHref" select="@href"/>

  <xsl:variable name="vUid">
   <xsl:for-each select="$vUniqHrefs">
    <xsl:if test=". = $vthisHref">
     <xsl:value-of select="position()"/>
    </xsl:if>
   </xsl:for-each>
  </xsl:variable>
   <a href="{@href}&amp;no_cache={{{$vUid}}}"/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<t>
 <link href="1.html"/>
 <a>
   <link href="2.html"/>
  <b>
    <link href="1.html"/>
    <c>
     <link href="3.html"/>
    </c>
    <link href="2.html"/>
  </b>
  <link href="1.html"/>
  <d>
   <link href="3.html"/>
  </d>
 </a>
 <link href="4.html"/>
 <e>
  <link href="2.html"/>
 </e>
 <link href="4.html"/>
</t>

产生了想要的正确结果

<t>
   <a href="1.html&amp;no_cache={1}"/>
   <a>
      <a href="2.html&amp;no_cache={2}"/>
      <b>
         <a href="1.html&amp;no_cache={1}"/>
         <c>
            <a href="3.html&amp;no_cache={3}"/>
         </c>
         <a href="2.html&amp;no_cache={2}"/>
      </b>
      <a href="1.html&amp;no_cache={1}"/>
      <d>
         <a href="3.html&amp;no_cache={3}"/>
      </d>
   </a>
   <a href="4.html&amp;no_cache={4}"/>
   <e>
      <a href="2.html&amp;no_cache={2}"/>
   </e>
   <a href="4.html&amp;no_cache={4}"/>
</t>

答案 1 :(得分:3)

尝试generate-id()。

<xsl:value-of select="generate-id(.)"/>

这是进一步的解释:http://www.w3schools.com/XSL/func_generateid.asp

答案 2 :(得分:2)

使用纯XSLT是不可能的,但是一些替代选项可能是:

  1. 添加扩展名称空间,以便您可以调用非XSLT代码:<a href="1.html&no_cache={myns:unique_id()}">。这将为您提供您所追求的结果,但取决于您用于执行转换的框架的支持。
  2. 使用JavaScript将唯一ID添加到客户端上的链接。仅在您的客户启用了JavaScript时才有效,但如果您知道情况属实,则可能是可接受的妥协。
  3. 在页面上设置HTTP标头以防止缓存。从语义的角度来看,这可能是最好的选择,并且您不会冒着搜索引擎使用每个唯一ID重复抓取您的网页的风险。

答案 3 :(得分:0)

XSLT是一种函数式语言,对于给定的输入,它总是产生相同的输出,因此根据定义,guid方法或任何其他随机生成器不会成为设计规范的一部分。如果您受到客户约束,最好的选择是使用与时间相关的方法作为generate-id的伪随机种子的一部分,但是由于您的目标似乎是强大的分析,您应该放弃这个并且只关注应用正确的对您要保护的资源的反缓存标头。