2012-01-03 2 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 속성이있는 템플릿의 반환 유형을 지정하십시오. 이러한 변화는 임의의 XML 문서 (사용되지 않음)에인가된다

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

, 원하는 정확한 결과 생산된다 :

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

이것은 제가 찾고 있던 한 가지입니다. 나는 그것을 밖으로 시도 할 것이다! 고마워. – Kangkan

+0

@Kangkan : 천만에요. –

+1

@MatthewSimoneau, http : //stackoverflow.com/questions/12568962/what-is-the-difference-between-using-xslt-xslelement-and-declaring-elements-l/12575580#comment44506877_12575580 –

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 속성 (예 : = "node() *")을 사용하여 지정할 수 있으며 xsl : sequence 명령을 사용하여 결과를 XPath 표현식의 결과로 설정할 수 있습니다.

XSLT 1.0에서 변수에 xsl : call-template의 결과를 캡처하면 변수 값은 항상 결과 트리 조각이됩니다.

+0

당신은 맞다. XSLT 2.0을 사용 중입니다. – Kangkan

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/> 
관련 문제