XSLT 1.0是否支持中间结果? [英] Does XSLT 1.0 support intermediate results?
问题描述
TL; DR:如何用XPath表示<apply-templates />
语句?
TL;DR: How can I represent an <apply-templates />
statement with XPath?
我有一个整理信息的模板.我想以一种以上不同的方式进一步处理这些信息,所以我想知道是否存在一种从XSLT中的模板中返回"某种方式的方法.
I've got a template that collates information. I'd like to further process this information in more than one different way, so I was wondering whether there was a way to sort of "return" from a template in XSLT.
示例:我有一个XHTML代码段:
Example: I've got an XHTML snippet:
<page html:xmlns="html namespace">
<html:p>
The <html:a href="/foo">Tropical Foo</html:a> uses <html:a href="bar-language">Bar</html:a> to implement <html:a href="/programs/fizzbuzz>FizzBuzz</html:a>
</html:p>
</page>
我有一个模板,可以从HTML代码段中提取带有href
的<a>
标签.我想重复使用两次以预取页面 并添加一个链接"栏,如下所示:
I've got a template to extract <a>
tags with an href
from an HTML snippet. I'd like to reuse this twice to both prefetch the pages and add a "Linked" bar, like so:
<html>
<head>
<link rel="prefetch" href="/foo" />
<link rel="prefetch" href="bar-language" />
<link rel="prefetch" href="/programs/fizzbuzz" />
</head>
<body>
<main>
<p>
The <a href="/foo">Tropical Foo</a> uses <a href="bar-language">Bar</a> to implement <a href="/programs/fizzbuzz>FizzBuzz</a>
</p>
</main>
<aside>
<h2>Linked</h2>
<ul>
<li><a href="/foo">Tropical Foo</a></li>
<li><a href="bar-language">Bar</a></li>
<li><a href="/programs/fizzbuzz>FizzBuzz</a></li>
</ul>
</aside>
</body>
</html>
在XSLT 1.0中可能吗?
Is this possible in XSLT 1.0?
如果比较容易,我可以通过使用样式表转换整个文档,然后使用转换后的版本来解决该问题.我知道我可以<xsl:include>
其他文档转换样式表并编写<xsl:apply-templates select="document('other.xml')"/>
,但是我想进一步转换此结果.
If it's easier, I've got a related variant of the problem where I'm transforming an entire document with a stylesheet, and then want to use the transformed version. I know I can <xsl:include>
the other-document-transforming stylesheet and write <xsl:apply-templates select="document('other.xml')"/>
, but I want to further transform the result of this.
推荐答案
XSLT 1.0将一种数据类型添加到从XPath 1.0数据模型中合并的四种数据类型(字符串,数字,布尔值,节点集)中:结果树片段( https://www.w3.org/TR/xslt -10/#section-Result-Tree-Fragments ):
XSLT 1.0 adds one data type to the four (string, number, boolean, node-set) incorporated from the data model of XPath 1.0: result tree fragments (https://www.w3.org/TR/xslt-10/#section-Result-Tree-Fragments):
此附加数据类型称为结果树片段.一个变量 可能绑定到结果树片段,而不是四个之一 基本的XPath数据类型(字符串,数字,布尔值,节点集).结果 树片段表示结果树的片段.结果树 片段等同于仅包含一个 单根节点.但是,结果树上允许的操作 片段是节点集上允许的那些子集.一个手术 仅当该结果树片段被允许时,才允许该结果树片段 允许在字符串上使用(对字符串的操作可能首先涉及 将字符串转换为数字或布尔值).特别是 不允许在结果树上使用
/
,//
和[]
运算符 碎片.
This additional data type is called result tree fragment. A variable may be bound to a result tree fragment instead of one of the four basic XPath data-types (string, number, boolean, node-set). A result tree fragment represents a fragment of the result tree. A result tree fragment is treated equivalently to a node-set that contains just a single root node. However, the operations permitted on a result tree fragment are a subset of those permitted on a node-set. An operation is permitted on a result tree fragment only if that operation would be permitted on a string (the operation on the string may involve first converting the string to a number or boolean). In particular, it is not permitted to use the
/
,//
, and[]
operators on result tree fragments.
因此,您可以将中间结果作为结果树的片段,但是如果您希望使用除xsl:copy-of
或xsl:value-of
以外的任何东西,或者获取字符串值,则需要超越XSLT 1.0,并且在大多数XSLT 1.0处理器中,您都可以支持对于像exsl:node-set
这样的扩展功能,它将结果树片段转换为节点集.
So you can have intermediary results as result tree fragments but if you expect to use anything more than xsl:copy-of
or xsl:value-of
or taking the string value you need to go beyond XSLT 1.0 and in most XSLT 1.0 processors you have support for an extension function like exsl:node-set
to do that, it converts a result tree fragment to a node-set.
这是一个简单的示例,该示例首先处理输入中的某些元素以添加属性,然后使用exsl:node-set
(
Here is a simple example that first processes some elements from an input to add an attribute and converts that result tree fragment into a node-set using exsl:node-set
(http://exslt.org/exsl/functions/node-set/index.html) to then use that node-set twice for two different modes:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="exsl msxml"
version="1.0">
<xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>
<xsl:variable name="numbered-items-rtf">
<xsl:apply-templates select="//item" mode="number"/>
</xsl:variable>
<xsl:variable name="numbered-items" select="exsl:node-set($numbered-items-rtf)/item"/>
<xsl:template match="item" mode="number">
<xsl:copy>
<xsl:attribute name="index">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
<style>
nav ul li { display: inline }
nav ul { list-item-type: none }
</style>
</head>
<body>
<h1>Example</h1>
<nav>
<ul>
<xsl:apply-templates select="$numbered-items" mode="nav"/>
</ul>
</nav>
<section>
<h2>List</h2>
<ul>
<xsl:apply-templates select="$numbered-items"/>
</ul>
</section>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<li id="item-{@index}">
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="item" mode="nav">
<li>
<a href="#item-{@index}">
<xsl:apply-templates/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
像
<root>
<items>
<item>foo</item>
<item>bar</item>
<item>baz</item>
</items>
</root>
转换为
<!DOCTYPE html SYSTEM "about:legacy-doctype">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-16">
<title>.NET XSLT Fiddle Example</title>
<style>
nav ul li { display: inline }
nav ul { list-item-type: none }
</style>
</head>
<body>
<h1>Example</h1><nav><ul>
<li><a href="#item-1">foo</a></li>
<li><a href="#item-2">bar</a></li>
<li><a href="#item-3">baz</a></li>
</ul></nav><section><h2>List</h2>
<ul>
<li id="item-1">foo</li>
<li id="item-2">bar</li>
<li id="item-3">baz</li>
</ul></section></body>
</html>
https://xsltfiddle.liberty-development.net/pPqsHUd/1
缺点是某些XSLT 1.0处理器不支持exsl:node-set
功能,但在专有名称空间中类似(例如,基于Microsoft COM的MSXML(3,4,5,6)处理器仅支持msxml:node-set
在名称空间xmlns:msxml="urn:schemas-microsoft-com:xslt"
中,就像(过时的)基于.NET的XslTransform
一样).当然,只要您瞄准单个XSLT 1.0处理器,您当然就可以使您的代码适应使用正确的名称空间/扩展功能,但是如果您要针对不同的名称空间/扩展功能,则将很难找到一种紧凑而优雅的方式来基于以下功能使用不同的扩展功能function-available
,因为您在XPath 1.0中没有if
表达式.
The draw back is that some XSLT 1.0 processors don't support the exsl:node-set
function but a similar in a proprietary namespace (for instance Microsoft's COM based MSXML (3,4,5,6) processors only support msxml:node-set
in the namespace xmlns:msxml="urn:schemas-microsoft-com:xslt"
, like does the (obsolete) .NET based XslTransform
). As long as you target a single XSLT 1.0 processor you can of course adapt your code to use the right namespace/extension function but if you want to target different ones you will struggle to find a compact and elegant way to use different extension functions based on function-available
as you don't have an if
expression in XPath 1.0.
因此 https://xsltfiddle.liberty-development.net/pPqsHUd/2与例如Chrome和Firefox等Mozilla浏览器确实支持exsl:node-set
,但在Microsoft IE和Edge中却无法使用,因为它们使用MSXML并且不支持exsl:node-set
,因为它们需要<xsl:variable name="numbered-items" select="msxml:node-set($numbered-items-rtf)/item"/>
,如
So https://xsltfiddle.liberty-development.net/pPqsHUd/2 works with e.g. Chrome and with Mozilla browsers like Firefox as these browsers do support exsl:node-set
but fails in Microsoft IE and Edge as these use MSXML and don't support exsl:node-set
, for them you need <xsl:variable name="numbered-items" select="msxml:node-set($numbered-items-rtf)/item"/>
as done in https://xsltfiddle.liberty-development.net/pPqsHUd/3.
在IE中,您可以使用脚本扩展来使其支持exsl:node-set
,但是不幸的是,在Edge中,此扩展不起作用: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7598626/.
In IE you can use a script extension to have it support exsl:node-set
but unfortunately in Edge this doesn't work: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7598626/.
这篇关于XSLT 1.0是否支持中间结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!