我正在使用带有几个XML文件的XSLT来生成我的网页。我希望能够在我的XML中添加一个<widget name="example" />
小部件标记,它将小部件插入到html中的相应位置。此小部件也由XML文件定义,该文件定义其html内容和其他信息。
这很顺利,但现在小部件需要一个或多个脚本,它定义为
<scripts>
<script>jquery<script>
<script>animation</script>
</scripts>
我想将此脚本添加到html的head标记中,而不是在整个地方散布脚本标记。我使用的当前方法如下:我构建我的页面并将其放入变量,如:
<xsl:template match="/">
<xsl:variable name="document">
<html>
<head>
<title><xsl:value-of select="page/title" /></title>
<xsl:apply-templates select="/page/scripts" mode="content" />
<xsl:apply-templates select="/page/sheets" mode="content" />
</head>
<body>
<div class="header">
<h1><xsl:value-of select="page/title" /></h1>
</div>
<xsl:apply-templates select="$menu/menu" mode="menu" />
<div class="content">
<xsl:apply-templates select="page/content/*" mode="content" />
</div>
</body>
</html>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($document)" mode="collect-resources" />
</xsl:template>
这会将scripts
标记留在原处。在此之后,我打电话给
<xsl:apply-templates select="exsl:node-set($document)" mode="collect-resources" />
导致以下模板:
<xsl:template match="head" mode="collect-resources">
<xsl:for-each select="..//scripts">
<xsl:apply-templates select="current()/*" mode="scripts" /> <!-- Convert the scripts defined in this scripts tag into proper HTML script tags. -->
</xsl:for-each>
</xsl:template>
<xsl:template match="scripts" mode="collect-resources" /> <!-- Remove all scripts tags. -->
<xsl:template match="node()" mode="collect-resources">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="./node()" mode="collect-resources"/>
</xsl:copy>
</xsl:template>
其中两次遍历整个文档:一次收集所有脚本标记以将脚本放入标题中,第二次删除所有scripts
标记。
对于较大的文档,这变得非常慢,并且有点脏。有没有办法做到更整洁和/或更快?
附录I - widget.xml
<widget>
<scripts>
<script>/widgets/example/main</script>
</scripts>
<content>
<div class="example-widget" />
</content>
</widget>
附录II - template.xsl
<xsl:template match="widget" mode="content">
<xsl:variable name="path">../widgets/<xsl:value-of select="@name" />/widget.xml</xsl:variable> <!-- The path to the widget xml -->
<xsl:variable name="widget" select="document($path)"/>
<xsl:element name="div">
<xsl:attribute name="class">widget</xsl:attribute>
<xsl:apply-templates select="$widget/widget/scripts" mode="content" /> <!-- Copy the widget script information. -->
<xsl:apply-templates select="$widget/widget/content/*" mode="content" /> <!-- Copy the widget contents. -->
</xsl:element>
</xsl:template>
<xsl:template match="node()" mode="content"> <!-- Copy anything that is not a widget. -->
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="./node()" mode="content" />
</xsl:copy>
</xsl:template>
答案 0 :(得分:1)
似乎在你的
里面 <head>
<title><xsl:value-of select="page/title" /></title>
<xsl:apply-templates select="/page/scripts" mode="content" />
<xsl:apply-templates select="/page/sheets" mode="content" />
</head>
您希望确保直接处理任何widget
及其链接脚本,例如
<head>
<title><xsl:value-of select="page/title" /></title>
<xsl:apply-templates select="/page/scripts" mode="content" />
<xsl:apply-templates select="//widget" mode="script"/>
<xsl:apply-templates select="/page/sheets" mode="content" />
</head>
和
<xsl:template match="widget" mode="script">
<xsl:variable name="path">../widgets/<xsl:value-of select="@name" />/widget.xml</xsl:variable> <!-- The path to the widget xml -->
<xsl:variable name="widget" select="document($path)"/>
<xsl:apply-templates select="$widget/widget/scripts" mode="scripts" />
</xsl:template>
然后在另一个模板中,您将不输出脚本
<xsl:template match="widget" mode="content">
<xsl:variable name="path">../widgets/<xsl:value-of select="@name" />/widget.xml</xsl:variable> <!-- The path to the widget xml -->
<xsl:variable name="widget" select="document($path)"/>
<xsl:element name="div">
<xsl:attribute name="class">widget</xsl:attribute>
<xsl:apply-templates select="$widget/widget/content/*" mode="content" /> <!-- Copy the widget contents. -->
</xsl:element>
</xsl:template>
你必须衡量这是否表现更好。