2010-12-22 111 views
6

我想將XML文檔轉換爲HTML。一些XML元素有聯繫的其他文件,如:如何生成唯一的字符串

<link href="1.html"> 

在HTML輸出,我想:

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

我怎麼能產生這種獨特的相當大的ID?

+0

[generate-id()](http://www.w3schools.com/XSL/func_generateid.asp)。 – khachik 2010-12-22 13:36:26

+1

不適合我的情況。如果我嘗試多次處理這個xml,generate-id()不會生成唯一的ID。我想每次都有唯一的ID – Nawa 2010-12-22 14:20:57

+0

好問題,+1。查看我的答案,獲取完整而簡短的XSLT解決方案。 :) – 2010-12-22 16:19:33

回答

5

首先,我假設由於某些未知原因,您無法使用link中的絕對URL作爲所需的UID--這是最簡單也是最自然的解決方案。

如果我的假設是正確的,那麼:

這是XSLT一件容易的事。

由於OP希望生成的id在執行多次轉換時是相同的,因此不適合使用generate-id()函數。

這裏是產生穩定的IDS的一個簡單的方法:

<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> 
0

XSLT是一種功能性的語言,這意味着對於給定輸入它將總是產品相同的輸出,所以通過定義一個GUID方法或任何其他隨機發生器就不會成爲設計規範的一部分。你最好的選擇是,如果你的客戶端綁定的是使用時間相關的方法作爲generate-id的僞隨機種子的一部分,但是由於你的目標似乎很強,所以你應該放棄這個,只關注應用正確的反緩存標題到您正在嘗試保護的資源。

2

這是不可能用純XSLT,但一些替代方案可能是:

  1. 添加擴展名的命名空間,這樣就可以叫出非XSLT代碼:<a href="1.html&no_cache={myns:unique_id()}">。這會給你你想要的結果,但是取決於你用來執行轉換的框架的支持。
  2. 使用JavaScript將唯一ID添加到客戶端上的鏈接。只有當您的客戶端啓用了JavaScript時纔有效,但如果您知道情況會如此,則可能是可以接受的折中方案。
  3. 在頁面上設置HTTP標頭以防止緩存。從語義的角度來看,這可能是最好的選擇,並且您不會冒着搜索引擎重複抓取每個唯一ID的頁面的風險。
相關問題