XSLT1.0-条件节点分配
使用纯XSLT1.0,如何有条件地分配节点。我正在尝试类似的东西,但它不起作用XSLT1.0-条件节点分配,xslt,xpath,Xslt,Xpath,使用纯XSLT1.0,如何有条件地分配节点。我正在尝试类似的东西,但它不起作用 <xsl:variable name="topcall" select="//topcall"/> <xsl:variable name="focusedcall" select="//focusedcall" /> <xsl:variable name="firstcall" select="$topcall | $focusedcall"/> 对于变量firstcall
<xsl:variable name="topcall" select="//topcall"/>
<xsl:variable name="focusedcall" select="//focusedcall" />
<xsl:variable name="firstcall" select="$topcall | $focusedcall"/>
对于变量firstcall
,我正在进行条件节点选择。如果有一个topcall
,则将其分配给firstcall
,其他人将firstcall
分配给focusedcall
您想做什么?这通常是按照不同类型节点的文档顺序获取第一个节点的方式。这应该可以:
<xsl:variable name="firstcall" select="$topcall[$topcall] |
$focusedcall[not($topcall)]" />
但是,在XSLT1.0中,这将把所选结果的输出转换为结果树片段(RTF:基本上是一个冻结的XML子树)。之后,您将无法在$firstcall
上使用任何重要的XPath表达式从中选择内容。如果以后需要在$firstcall
上进行XPath选择,例如select=“$firstcall[1]”
,那么您有几个选项
或
中,以便在数据转换为RTF之前进行选择。或者node-set()
扩展,它将RTF转换为节点集,因此您可以从中进行正常的XPath选择。此扩展在大多数XSLT处理器中可用,但并非所有处理器都可用。或者($focusedcall[$focusedcall] | $thiscall[not($focusedcall)])
在下一次迭代中,您将使用
($thiscall[$thiscall] | $thatcall[not($thiscall)])
等等
当然,这变得很难理解,而且容易出错,因此除非其他选项不可行,否则我不会选择此选项。I.XSLT 1.0解决方案此简短(30行)的简单参数化转换适用于任意数量的节点类型/名称:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pRatedCalls">
<call type="topcall"/>
<call type="focusedcall"/>
<call type="normalcall"/>
</xsl:param>
<xsl:variable name="vRatedCalls" select=
"document('')/*/xsl:param[@name='pRatedCalls']/*"/>
<xsl:variable name="vDoc" select="/"/>
<xsl:variable name="vpresentCallNames">
<xsl:for-each select="$vRatedCalls">
<xsl:value-of select=
"name($vDoc//*[name()=current()/@type][1])"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select=
"//*[name()
=
substring-before(normalize-space($vpresentCallNames),' ')]"/>
</xsl:template>
</xsl:stylesheet>
准确地生成所需的正确结果:
<topcall/>
<t>
<normalcall/>
<focusedcall/>
</t>
<focusedcall/>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pRatedCalls" select=
"'topcall', 'focusedcall', 'normalcall'"/>
<xsl:template match="/">
<xsl:sequence select=
"//*
[name()=$pRatedCalls
[. = current()//*/name()]
[1]
]"/>
</xsl:template>
</xsl:stylesheet>
马丁-我也试过,但似乎不起作用。我们已经为topcall和focusedcall定义了节点。使用此条件节点分配,我希望第一个调用分配topcall(如果它存在),否则focusedcall。仅供参考,在输入xml中,focusedcall首先出现在topcall之前。@rpg:“它不工作”需要更好地指定。你得到了什么样的结果,它与你的期望有什么不同?还有一点,这一点或不仅仅是两个,它可以是5-6个节点。此外,topcall和focusedcall的位置可能会发生变化,因此我似乎很难依赖与文档顺序相关的任何内容。@rpg-这是您需要在问题中包含的所有信息。如果有更重要的细节,请编辑以包含您的实际问题。如果您将“|”替换为“,”,则这是XSLT 2.0惯用法。一般情况下,它在XSLT1.0中不起作用,因为“|”按文档顺序返回节点。如果您知道当两个节点都存在时,$topcall将始终位于$focusedcall之前,那么可以使用它,因为我对XSLT非常陌生。条形码是联合运算符(不是逻辑的
或)。你之前是两个节点集的并集。LarsH的解决方案采用两个互斥集的并集,这总是导致一个或另一个。@rgp:是的,这是XSLT 1.0的解决方案。@LarsH-感谢您的精彩解释。但我仍然不清楚5-6个节点的例子。5-6个节点,我的意思是类似于topcall、focusedcall,我也可能有this call、that call等。在这种情况下,我如何找到第一个调用。@rpg-我更新了关于3个或更多备选方案的答案。+1,很好的解决方案。这充分利用了OP的备选方案严格基于元素名称这一事实。我正在为任何节点集变量创建一个更通用的解决方案,无论其内容如何。。。但是你已经指出这个问题没有必要了。@Dimitre-谢谢你的广义解决方案。对于一个新的例子,请看@rpg的第一句话:我已经添加了XSLT1.0解决方案的详细说明。请询问您可能还有的其他问题。
<t>
<normalcall/>
<focusedcall/>
</t>
<focusedcall/>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pRatedCalls" select=
"'topcall', 'focusedcall', 'normalcall'"/>
<xsl:template match="/">
<xsl:sequence select=
"//*
[name()=$pRatedCalls
[. = current()//*/name()]
[1]
]"/>
</xsl:template>
</xsl:stylesheet>