Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XSLT1.0-条件节点分配_Xslt_Xpath - Fatal编程技术网

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

使用纯XSLT1.0,如何有条件地分配节点。我正在尝试类似的东西,但它不起作用

<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处理器中可用,但并非所有处理器都可用。或者
  • 考虑使用XSLT2.0,其中RTF根本不是问题。事实上,在XPath2.0中,如果愿意,可以在XPath表达式中放入普通的if/then/else条件
  • 在XPath1.0中实现它,使用嵌套谓词,如
  • :

    并在必要时继续筑巢。换句话说,我在这里使用了上面两个备选方案的XPath表达式,并将$focusedcall替换为

    ($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>