2012-01-03 73 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/>