下面是一些一直困惑我,XSLT:
- 在什么样的顺序做模板执行和
- 当他们执行,做他们上的(a)的原始源XML,或(b)的XSLT的电流输出到该点匹配吗?
例:
<person>
<firstName>Deane</firstName>
<lastName>Barker</lastName>
</person>
这里是XSLT的一个片段:
<!-- Template #1 -->
<xsl:template match="/">
<xsl:value-of select="firstName"/> <xsl:value-of select="lastName"/>
</xsl:template>
<!-- Template #2 -->
<xsl:template match="/person/firstName">
First Name: <xsl:value-of select="firstName"/>
</xsl:template>
这个两个问题:
- 我假设模板#1将首先执行。 我不知道为什么我认为这一点 - 它只是因为它第一次出现在文档中?
- 将模板#2执行? 它匹配源XML节点,而是由当时的我们得到这个模板(假设它运行第二次),在“名字”节点将不会在输出树。
那么,受惠于发生在“早期”模板是什么“后”的模板,或者他们对源文件进行操作,无视于已经转化“之前”给他们吗? (所有这些话是加引号的,因为我觉得很难讨论基于时间的问题时,我真的没有什么想法模板顺序是如何在第一时间确定...)
在上面的例子中,我们有根节点(“/”)上匹配的模板 - 当它完成执行 - 基本上已经除去来自输出的所有节点。 既然如此,从执行,因为没有什么后第一个模板是完全匹配的将这种越俎代庖的所有其他模板?
对于这一点,我一直在关注不执行,因为他们已经在运行的节点不输出出现后的模板,但什么反? 一个“早”模板可以创建一个“后来的”模板可以做一些与节点?
在与上述相同的XML,考虑这个XSL:
<!-- Template #1 -->
<xsl:template match="/">
<fullName>
<xsl:value-of select="firstName"/> <xsl:value-of select="lastName"/>
</fullName>
</xsl:template>
<!-- Template #2 -->
<xsl:template match="//fullName">
Full Name: <xsl:value-of select="."/>
</xsl:template>
模板#1创建了一个名为“全名”新节点。 同一节点上的模板#2场比赛。 将模板#2执行,因为“全名”节点由我们避开模板#2输出的时候存在?
我意识到,我深深的无知有关XSLT的“禅”。 到今天为止,我已经样式由根节点匹配的模板,然后从那里完全程序。 我厌倦了这样做的。 我宁愿其实正确理解XSLT,因此我的问题。
我爱你的问题。 你是什么,你还不知道很善于表达。 你只需要一些东西来绑东西放在一起。 我的建议是,你阅读“XSLT是如何工作的” ,一章我写就是为了解决你提出的问题。 我喜欢听到的话,它关系的东西放在一起给你。
不那么正式,我带你去一个刺在每个回答你的问题。
- 在什么样的顺序做模板执行和
- 当他们执行,做他们上的(a)的原始源XML,或(b)的XSLT的电流输出到该点匹配吗?
在XSLT处理任何给定的点,还有,在一定意义上,两个上下文,你标识为(A)和(B):你在哪里,在源代码树 ,和您身在何处结果树 。 你在哪里在源树被称为当前节点 。 它可以改变和跳跃周围所有的源代码树,任您选择节点的任意组使用XPath来处理。 然而,在概念上,你永远不“跳来跳去”结果树以同样的方式。 XSLT处理器构建它以有序的方式; 第一它产生结果树的根节点; 然后它增加了儿童,建立结果文档顺序(深度优先)。 [您的帖子促使我再次拿起我的XSLT实验软件的可视化...]
的模板规则在样式表的顺序从未事项。 你不能告诉,只是通过看样式,以什么顺序的模板规则将被实例化,多少次的规则将被实例化,或者甚至是否会在所有。 ( match="/"
是个例外,你可以随时知道它会被触发。)
我假设模板#1将首先执行。 我不知道为什么我认为这一点 - 它只是因为它第一次出现在文档中?
不。 这将是第一个,即使你把它放在最后一个文档中调用。 模板规则的顺序从未事项(除错误情况下,当你有相同的优先级相匹配的同一节点不止一个模板规则,即使在当时,它是可选的实现者,你永远不应该依赖于这种行为)。 这被称为第一,因为当你运行一个XSLT处理器,它总是会发生的第一件事情是一个虚拟调用<xsl:apply-templates select="/"/>
在一个虚拟呼叫构建整个结果树。 什么也没有发生外面。 您可以通过定义模板规则去定制,或“配置”,该指令的行为。
将模板#2执行? 它匹配源XML节点,而是由当时的我们得到这个模板(假设它运行第二次),在“名字”节点将不会在输出树。
模板#2(或任何其他模板规则)将永远不会被触发,除非你有一个<xsl:apply-templates/>
在某处调用match="/"
规则。 如果你没有任何,那么没有模板规则比其他match="/"
将被触发。 认为它是这样的:为得到触发模板规则,它不能只匹配输入节点。 它以匹配您选择过程中的一个节点(使用<xsl:apply-templates/>
相反,它会继续节点多次搭配任你选择对其进行处理。
请问[的match="/"
模板]抢先从执行,因为没有什么可匹配后第一模板完成所有其他的模板?
这条规则被无处包括抢占其余<xsl:apply-templates/>
在里面。 还有很多, 可以在源代码树进行处理节点。 他们始终都在那里,成熟采摘; 只要你想处理每一个多次。 但是,使用模板规则来处理它们的唯一方法是调用<xsl:apply-templates/>
对于这一点,我一直在关注不执行,因为他们已经在运行的节点不输出出现后的模板,但什么反? 一个“早”模板可以创建一个“后来的”模板可以做一些与节点?
这并不是说一个“早”模板创建要处理的新节点; 它是一个“早”模板依次处理多个节点从源代码树,使用相同的指令( <xsl:apply-templates
)。 你可以把它看作是每次(处理节点如上下文和确定调用同一个“功能”递归,使用不同的参数select
属性)。
最终,你得到的是递归调用相同的“功能”的树形结构栈( <xsl:apply-templates>
)。 而这种树状结构同构于您的实际结果。 不是每个人都意识到了这一点或者已经想过这种方式; 那是因为我们没有任何有效的可视化工具...但。
模板#1创建了一个名为“全名”新节点。 同一节点上的模板#2场比赛。 将模板#2执行,因为“全名”节点由我们避开模板#2输出的时候存在?
不。 做加工链中的唯一方法是显式设置了这种方式。 创建一个变量,例如, $tempTree
,包含新的<fullName>
元素,然后对其进行处理,像这样<xsl:apply-templates select="$tempTree">
要做到这一点在XSLT 1.0,你需要用与扩展功能变量引用(例如, exsl:node-set()
但在XSLT 2.0,将工作就像是。
无论您是从原来的源目录,或者在你建立一个临时的树,无论何种方式的处理节点,你需要明确地说要处理哪些节点。
我们还没有涉及XSLT是如何得到它的所有隐式的行为。 你还必须了解内置的模板规则 。 我写的样式表所有的时间甚至不包括根节点的明确规则( match="/"
)。 相反,我依靠根节点内置规则(应用模板儿童),这是一样的元素节点内置的规则。 因此,我可以忽略输入的大部分地区,让XSLT处理器自动遍历它,当它涉及只能隔着我感兴趣的是我会做一些特殊的节点。 或者,我可以写一个规则,副本的一切递归(称为恒等变换),覆盖只在必要时做出的输入增量变化。 你读过“如何XSLT工程”后,你的下一个任务是查找的“身份转换”。
我意识到,我深深的无知有关XSLT的“禅”。 到今天为止,我已经样式由根节点匹配的模板,然后从那里完全程序。 我厌倦了这样做的。 我宁愿其实正确理解XSLT,因此我的问题。
我为你鼓掌。 现在是时候采取了“红色药丸”:读“如何XSLT工程”
模板总是匹配源XML。 所以为了其实并不重要,除非2个或多个模板匹配相同的节点(一个或多个)。 在这种情况下,有些违反直觉,与上次匹配模板触发规则。
在您的第一示例模板#1运行,因为当你开始处理它开始在根输入XML,这是在样式表的根元素相匹配的唯一模板。 即使在样式表是第二个它仍然会运行第一次。
在本例中为您已使用模板1已经处理的根元素,有没有更多的元素的根之后处理模板2将不会运行。 如果你确实想过程中使用其他模板等元素,你应该改变它。
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
这就允许你定义你感兴趣的每个元素模板,以更合理的方式处理XML,而不是程序上做这件事。
另外请注意,这个例子也不会输出任何东西作为当前上下文(根)不存在的firstName元素,只有一个人的要素,所以应该是:
<xsl:template match="/">
<xsl:value-of select="person/firstName"/> <xsl:value-of select="person/lastName"/>
</xsl:template>
我觉得它更容易认为你是通过XML步进,从根开始,寻找该元素然后按照这些指令生成德输出相匹配的模板。 在XSLT转换输入文档到输出,使输出doucument处于转变的开始是空的。 输出不作为转型的一部分,它只是从它的输出。
在你的第二个例子,因为该模板对输入XML不输出运行模板#2将不会执行。
埃文的回答基本上是一个很好的一个。
然而一两件事似乎有所欠缺是“呼”起来的代码块没有做任何匹配的能力。 这 - 至少在某些人看来 - 能够更好的结构。
我已经在试图说明我的意思做了一个小例子。
<xsl:template match="/" name="dotable">
<!-- Surely the common html part could be placed somewhere else -->
<!-- the head and the opening body -->
<html>
<head><title>Salary table details</title></head>
<body>
<!-- Comments are better than nothing -->
<!-- but that part should really have been somewhere else ... -->
<!-- Now do what we really want here ... this really is making the table! -->
<h1>Salary Table</h1>
<table border = "3" width="80%">
<xsl:for-each select="//entry">
<tr>
<td><xsl:value-of select="name" /></td>
<td><xsl:value-of select="firstname" /></td>
<td><xsl:value-of select="age" /></td>
<td><xsl:value-of select="salary" /></td>
</tr>
</xsl:for-each>
</table>
<!-- Now close out the html -->
</body>
</html>
<!-- this should also really be somewhere else -->
<!-- This approach works, but leads to horribly monolithic code -->
<!-- Further - it leads to templates including code which is strictly -->
<!-- not relevant to them. I've not found a way round this yet -->
</xsl:template>
然而,摆弄了一下周围,并在第一次利用,如果有两个匹配模板代码的最后一个提示将被选中,然后重组我的代码(不是所有所示)后,我实现了这个似乎工作,并希望生成正确的代码,以及显示所需的数据 -
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- <?xml version="1.0"?>-->
<xsl:template name="dohtml">
<html>
<xsl:call-template name="dohead" />
<xsl:call-template name="dobody" />
</html>
</xsl:template>
<xsl:template name="dohead">
<head>
<title>Salary details</title>
</head>
</xsl:template>
<xsl:template name="dobody">
<body>
<xsl:call-template name="dotable" />
</body>
</xsl:template>
<xsl:template match="/entries" name="dotable">
<h1>Salary Table</h1>
<table border = "3" width="80%">
<xsl:for-each select="//entry">
<tr>
<td><xsl:value-of select="name" /></td>
<td><xsl:value-of select="firstname" /></td>
<td><xsl:value-of select="age" /></td>
<td><xsl:value-of select="salary" /></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="/" name="main">
<xsl:call-template name="dohtml" />
</xsl:template>
[滚动上面的代码上下,如果你不能看到这一切]
这种工作方式是主模板总是匹配 - 开/匹配
这样做的代码块 - 模板 - 这是所谓的。
现在,这意味着它无法与在其它模板/但它是可能的一个名为节点,在这种情况下是在XML中最高级别的节点上明确匹配 - 所谓的条目。
一个小的修改的代码产生上面给出的例子。
文章来源: In what order do templates in an XSLT document execute, and do they match on the source XML or the buffered output?