2012-01-03 42 views
3

我使用的搜索一些特定元素,比如这个递归模板:xsl:命名模板是否可以返回节点列表?

<xsl:template name="GetProdDependency"> 
    <xsl:param name="TechProd"></xsl:param> 
    <xsl:param name="BeatenPath"></xsl:param> 
    <xsl:variable name="TechProdArch" select="$TechProd/pro:own_slot_value[pro:slot_reference='technology_product_architecture']/pro:value"></xsl:variable> 
    <xsl:variable name="TechProdArchNode" select="/node()/pro:simple_instance[pro:name=$TechProdArch]"></xsl:variable> 
    <xsl:variable name="TechProdCompList" select="$TechProdArchNode/pro:own_slot_value[pro:slot_reference='contained_techProd_components']/pro:value"/> 
    <xsl:for-each select="$TechProdCompList"> 
     <xsl:variable name="TechProdAsRole" select="/node()/pro:simple_instance[pro:name=current()]/pro:own_slot_value[pro:slot_reference='technology_product_as_role']/pro:value"/> 
     <xsl:variable name="TechProdRole" select="/node()/pro:simple_instance[pro:name=$TechProdAsRole]/pro:own_slot_value[pro:slot_reference='role_for_technology_provider']/pro:value"/> 
     <xsl:variable name="DepTechProd" select="/node()/pro:simple_instance[pro:name=$TechProdRole]"/> 
     <!-- Check for beaten Path --> 
     <!-- if $DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value in BeatenPath --> 
     <xsl:if test="not($BeatenPath[string(.)=string($DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value)])"> 
      <!-- Do the recursion here! --> 
      <!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/> (type: <xsl:value-of select="$DepTechProd/pro:type"/> and Class: <xsl:value-of select="$DepTechProd/pro:name"/>)--> 
      <!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/>--> 
      <xsl:value-of select="$DepTechProd"/> 
      <xsl:call-template name="GetProdDependency"> 
       <xsl:with-param name="TechProd" select="$DepTechProd"></xsl:with-param> 
       <xsl:with-param name="BeatenPath" select="$TechProd|$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param> 
       <xsl:with-param name="Rev" select="$Rev + 1"></xsl:with-param> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

这是在搜索做工精细等

但是,当我得到的结果在原来的调用者,我是期望获得来自呼叫的节点列表。

我这样称呼它:

<xsl:variable name="DelPlist"> 
<xsl:call-template name="GetProdDependency"> 
    <xsl:with-param name="TechProd" select="$TechProd"></xsl:with-param> 
    <xsl:with-param name="BeatenPath" select="$TechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param> 
    <xsl:with-param name="Rev" select="1"></xsl:with-param> 
</xsl:call-template> 
</xsl:variable> 

我期待得到节点列表,我可以通过与<xsl:for-each>迭代。但是,如果我检查count($DelPlist),我得到1结果,我不能迭代。

有人可以帮忙吗?

回答

4

您必须在其as属性中指定模板结果的类型。

如果未指定,则类型为document-node(),然后为了遍历结果,需要获取结果的子项。

解决方案:使用as属性指定模板的返回类型。

下面是一个完整的例子

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:variable name="vNodes" as="element()*"> 
     <xsl:call-template name="genNodes"/> 
    </xsl:variable> 

    <xsl:for-each select="$vNodes"> 
     <xsl:value-of select="concat('&#xA;', position(), ': ')"/> 
     <xsl:copy-of select="."/> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template name="genNodes" as="element()*"> 
    <a/> 
    <b/> 
    <c/> 
</xsl:template> 
</xsl:stylesheet> 

当这种转化是在任何XML文档(未使用)施加时,想要的,正确的结果产生

1: <a/> 
2: <b/> 
3: <c/> 
+1

这是我一直在寻找的一件事。我会试试看!非常感谢。 – Kangkan 2012-01-03 14:34:27

+0

@Kangkan:不客气。 – 2012-01-03 15:16:04

+1

@MatthewSimoneau See; http://stackoverflow.com/questions/12568962/what-is-the-difference-between-using-xslt-xslelement-and-declaring-elements-l/12575580#comment44506877_12575580 – 2015-03-23 07:14:01

1

对不起。

我能达到什么样的符合我在下面amnner要求:

<xsl:template name="GetProdDependency"> 
    <xsl:param name="TechProd"></xsl:param> 
    <xsl:param name="BeatenPath"></xsl:param> 
    <xsl:variable name="TechProdArch" select="$TechProd/pro:own_slot_value[pro:slot_reference='technology_product_architecture']/pro:value"></xsl:variable> 
    <xsl:variable name="TechProdArchNode" select="/node()/pro:simple_instance[pro:name=$TechProdArch]"></xsl:variable> 
    <xsl:variable name="TechProdCompList" select="$TechProdArchNode/pro:own_slot_value[pro:slot_reference='contained_techProd_components']/pro:value"/> 
    <xsl:for-each select="$TechProdCompList"> 
     <xsl:variable name="TechProdAsRole" select="/node()/pro:simple_instance[pro:name=current()]/pro:own_slot_value[pro:slot_reference='technology_product_as_role']/pro:value"/> 
     <xsl:variable name="TechProdRole" select="/node()/pro:simple_instance[pro:name=$TechProdAsRole]/pro:own_slot_value[pro:slot_reference='role_for_technology_provider']/pro:value"/> 
     <xsl:variable name="DepTechProd" select="/node()/pro:simple_instance[pro:name=$TechProdRole]"/> 
     <!-- Check for beaten Path --> 
     <!-- if $DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value in BeatenPath --> 
     <xsl:if test="not($BeatenPath[string(.)=string($DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value)])"> 
      <!-- Do the recursion here! --> 
      <!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/> (type: <xsl:value-of select="$DepTechProd/pro:type"/> and Class: <xsl:value-of select="$DepTechProd/pro:name"/>)--> 
      <!--<xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"/>--> 
      <!--<xsl:value-of select="$DepTechProd"/>--> 
      <xsl:element name="TProd"> 
       <xsl:value-of select="$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value" /> 
      </xsl:element> 
      <xsl:call-template name="GetProdDependency"> 
       <xsl:with-param name="TechProd" select="$DepTechProd"></xsl:with-param> 
       <xsl:with-param name="BeatenPath" select="$TechProd|$DepTechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param> 
       <xsl:with-param name="Rev" select="$Rev + 1"></xsl:with-param> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

而且可以通过节点列表的迭代:

<xsl:variable name="DelPlist"> 
<xsl:call-template name="GetProdDependency"> 
    <xsl:with-param name="TechProd" select="$TechProd"></xsl:with-param> 
    <xsl:with-param name="BeatenPath" select="$TechProd/pro:own_slot_value[pro:slot_reference='name']/pro:value"></xsl:with-param> 
    <xsl:with-param name="Rev" select="1"></xsl:with-param> 
</xsl:call-template> 
</xsl:variable> 

<xsl:for-each select="$DelPlist/node()"> 
    <xsl:value-of select="current()" /> 
</xsl:for-each> 

它符合我目前的需求。

4

您的问题的答案是:在XSLT 2.0中是的,在XSLT 1.0中没有。

在XSLT 2.0中,模板和函数都可以返回任何值。可以使用as属性(例如as =“node()*”)指定结果的类型,并且可以使用xsl:sequence指令将结果设置为任何XPath表达式的结果。

在XSLT 1.0中,如果捕获变量中xsl:call-template的结果,变量的值将始终是结果树片段。

+0

你是正确的。我在XSLT 2.0上。 – Kangkan 2012-01-03 10:12:20

1

可能在xsl 1。0与EXSLT:节点集合(由最XSLT处理器支持):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exslt="http://exslt.org/common" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt" 
    exclude-result-prefixes="exslt msxml" 
    extension-element-prefixes="exslt msxml" 
    version="1.0"> 
    <!-- support for exslt prefix for msxml, ignored by other processors which however support exsl natively anyway --> 
    <msxml:script language="JScript" implements-prefix="exslt">this['node-set']=function(x){return x}</msxml:script> 
    <xsl:template match="/"> 
     <xsl:variable name="elementsReturnedFromCallTemplate"> 
      <xsl:call-template name="getElements"/> 
     </xsl:variable> 
     <xsl:for-each select="exslt:node-set($elementsReturnedFromCallTemplate)/*"> 
      <xsl:copy/> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template name="getElements"> 
     <a/> 
     <b/> 
    </xsl:template> 
</xsl:stylesheet> 

输出(在测试的libxslt,Xalan的,撒克逊,MSXML):

<a/> 
<b/>