我想将一个XML文档转换成HTML。一些XML元素具有指向其他文档的链接,例如:
在HTML输出中,我希望得到以下内容:
如何生成一个较大的唯一ID?
<link href="1.html">
在HTML输出中,我希望得到以下内容:
<a href="1.html&no_cache={unique_id}">
如何生成一个较大的唯一ID?
<link href="1.html">
<a href="1.html&no_cache={unique_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}&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&no_cache={1}"/>
<a>
<a href="2.html&no_cache={2}"/>
<b>
<a href="3.html&no_cache={3}"/>
<c>
<a href="4.html&no_cache={4}"/>
</c>
<a href="5.html&no_cache={5}"/>
</b>
<a href="6.html&no_cache={6}"/>
<d>
<a href="7.html&no_cache={7}"/>
</d>
</a>
<a href="8.html&no_cache={8}"/>
<e>
<a href="9.html&no_cache={9}"/>
</e>
<a href="10.html&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}&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&no_cache={1}"/>
<a>
<a href="2.html&no_cache={2}"/>
<b>
<a href="1.html&no_cache={1}"/>
<c>
<a href="3.html&no_cache={3}"/>
</c>
<a href="2.html&no_cache={2}"/>
</b>
<a href="1.html&no_cache={1}"/>
<d>
<a href="3.html&no_cache={3}"/>
</d>
</a>
<a href="4.html&no_cache={4}"/>
<e>
<a href="2.html&no_cache={2}"/>
</e>
<a href="4.html&no_cache={4}"/>
</t>
<xsl:for-each select="key('kHrefByVal',@href)[1]/.."><xsl:number level="any"/></xsl:for-each>
来提高性能。 - user357812<xsl:value-of select="generate-id(.)"/>
generate-id()
函数可以在同一转换期间为输入源中的每个节点提供唯一标识符。如果您需要一个永久唯一标识符,则需要实现一些像MD5这样的算法。 - user357812使用纯XSLT不可能实现这一点,但有一些替代选项:
<a href="1.html&no_cache={myns:unique_id()}">
。这将给您想要的结果,但取决于您用于执行转换的框架是否支持。XSLT是一种函数语言,这意味着对于给定的输入,它将始终产生相同的输出,因此按定义,GUID方法或任何其他随机生成器都不会成为设计规范的一部分。如果您的客户有要求,最好使用与时间相关的方法作为伪随机种子的一部分来生成ID,但是由于您的目标似乎是强大的反缓存,您应该放弃这一点,并专注于将正确的反缓存头应用于您试图保护的资源。