변수를 기준으로 이름 템플릿을 호출하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1233702

  •  22-07-2019
  •  | 
  •  

문제

가능한지 모르겠지만 어떻게 해야할지 궁금합니다 ...

다음 XSL이 있다고 가정 해 봅시다.

<xsl:template name="foo">
  Bla bla bla
</xsl:template>
...
<xsl:template name="bar">
  Bla bla bla
</xsl:template>
...
<xsl:template match="/">
  <xsl:if test="$templateName='foo'">
    <xsl:call-template name="foo"/>
  </xsl:if>
  <xsl:if test="$templateName='bar'">
    <xsl:call-template name="bar"/>
  </xsl:if>
</xsl:template>

XSL을 변경하여 같은 것을 읽을 수 있습니까?

<xsl:template match="/">
  <xsl:call-template name="$templateName"/>
</xsl:template>
도움이 되었습니까?

해결책

아니, 이건이야 불가능합니다 직접 불가능합니다. 전화 규칙은 다음과 같습니다.

<xsl:call-template name="QName" />

여기서 a Qname은 다음과 같이 정의됩니다:

QName ::= PrefixedName | UnprefixedName

PrefixedName   ::= Prefix ':' LocalPart
UnprefixedName ::= LocalPart

Prefix         ::= NCName
LocalPart      ::= NCName

기본적으로 이것은 "캐릭터 만, 표현 없음"으로 귀결됩니다. 다른 답변이 강조 하듯이 ~이다 실제로 동등한 일을하는 방법이지만 간단한 접근/순진한 접근 방식은 효과가 없습니다.

다른 팁

설명대로 정확하게는 불가능하지만 다른 곳에서 설정 한 일부 값을 기반으로 런타임에서 템플릿을 선택할 수 있으려면 그렇게 할 수있는 속임수가 있습니다. 아이디어는 이름이 지정된 템플릿이 고유 한 모드에서 해당 이름의 노드와 일치하도록하는 것입니다 (정상 변환을 엉망으로 만들지 않도록). 예를 들어:

<xsl:stylesheet ... xmlns:t="urn:templates">

  <!-- Any compliant XSLT processor must allow and ignore any elements 
       not from XSLT namespace that are immediate children of root element -->
  <t:templates>
    <t:foo/>
    <t:bar/>
  </t:templates>

  <!-- document('') is the executing XSLT stylesheet -->     
  <xsl:variable name="templates" select="document('')//t:templates" />

  <xsl:template name="foo" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template name="bar" match="t:foo" mode="call-template">
    Bla bla bla
  </xsl:template>

  <xsl:template match="/">
    <xsl:variable name="template-name" select="..." />
    <xsl:apply-templates select="$templates/t:*[local-name() = $template-name]"
                         mode="call-template"/>
  </xsl:template>

사용할 수 있습니다 <xsl:with-param> 안에 <xsl:apply-templates>, 당신은 평원으로 할 수있는 모든 것을 할 수 있습니다. <xsl:call-template>.

또한 위의 코드는 XSLT 확장을 사용하지 않기 위해 필요한 것보다 다소 길다. 프로세서가 지원되는 경우 exslt:node-set(), 그런 다음 직접 노드를 생성 할 수 있습니다 <xsl:element>, 및 사용 node-set() 결과 트리 조각을 평범한 노드로 변환하여 document('') 마구 자르기.

자세한 내용은 참조하십시오 fxsl -이 개념을 기반으로하는 XSLT 용 기능적 프로그래밍 라이브러리입니다.

누구의 미래 참조를 위해 :

다음은 Pavel Minaev의 답변을 기반으로하는 작업 예입니다. 내 부분에 대한 원래 생각은 없습니다. ;-) 나는 msxml : node-set을 사용하여 .NET에서 작동하도록 설명 된대로 (다소) 사용하도록 전환했습니다.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
    <xsl:variable name="templates">
        <templates>
            <foo />
            <bar />
        </templates>
    </xsl:variable>
    <xsl:template name="foo" match="foo" mode="call-template">
        <FooElement />
    </xsl:template>
    <xsl:template name="bar" match="bar" mode="call-template">
        <BarElement />
    </xsl:template>
    <xsl:template match="/">
        <Root>
            <xsl:variable name="template-name">bar</xsl:variable> <!-- Change this to foo to get the other template. -->
            <xsl:apply-templates select="msxsl:node-set($templates)/*/*[local-name() = $template-name]" mode="call-template" />
        </Root>
    </xsl:template>
</xsl:stylesheet>

업데이트: 아래 링크는 web.archive.org를 가리키기 위해 업데이트되었습니다. 불행히도 이상적으로는 모두를 만들었습니다. Exteme 마크 업 언어 회의 절차를 이용할 수 없음 ... 적시에, 나는이 두 기사에 더 영구적 인 장소를 찾을 것입니다.


이것은 구현됩니다 fxsl.

FXSL의 주요 원칙에 대한 좋은 설명이 있습니다.

다음 두 기사를 참조하십시오.

"FXSL 라이브러리를 사용하여 XSLT의 기능 프로그래밍"(XSLT 1.0), (PDF) at :

http://web.archive.org/web/20070710091236/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2003/novatchev01/eml2003novatchev01.pdf

(html) at :

http://conferences.idealliance.org/extreme/html/2003/novatchev01/eml2003novatchev01.html



"XSLT 2.0 및 FXSL을 사용한 고차 기능 프로그래밍"(PDF) at :

http://web.archive.org/web/2007022111927/http://www.idealliance.org/papers/extreme/proceedings/xslfo-pdf/2006/novatchev01/eml2006novatchev01.pdf

(html) at :http://conferences.idealliance.org/extreme/html/2006/novatchev01/eml2006novatchev01.html



FXSL을 사용하면 쉽고 우아하게 많은 문제를 해결할 수 있었는데, 이는 "XSLT에게는 불가능한 것 같습니다". 많은 예를 찾을 수 있습니다 여기.

나는 당신과 같은 문제가 많았다고 생각합니다. "외부"템플릿이 있었고 런타임에 설정된 일부 변수에 따라 다른 "내부"템플릿을 호출하고 싶었습니다. 역동적 인 방법을 위해 인터넷 검색으로 질문을 찾았습니다. <xsl:call-template>. 사용하여 해결했습니다 <xsl:apply-templates> 대신, 다음과 같이.

입력 XML (런타임에 생성)에는 다음의 선을 따라 무언가가 포함됩니다.

<template name="template_name_1"/>

"외부"템플릿의 XSL은 다음과 같습니다.

<xsl:apply-templates select="template"/>

(그만큼 select="template" 이 apply-templates에서 <template> 입력 XML에서 태그)

그리고 마지막으로 "내부"템플릿은 name 내 XML의 속성은 다음과 같습니다.

<xsl:template match="template[@name='template_name_1']">
    <!-- XSL / XHTML goes here -->
</xsl:template>

(다시, match="template[@name='xyz']" 이전을 말합니다 select="template" 그리고 차례로 <template> 태그와 그 name 입력 XML의 속성)

이런 식으로 입력 XML에서 제어하여 단순히 "템플릿"이라는 템플릿을 가질 수 있습니다.

이것은 당신이 해결하려고하는 것과 같은 문제는 아니지만이 페이지에서 다른 곳에서 언급 된 FSXL 솔루션보다 매우 가깝고 훨씬 간단하다고 생각합니다.

이건 어때?:

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

      <xsl:template match="xsl:template[@name='foo']" name="foo">
    Bla bla bla foo
      </xsl:template>

      <xsl:template match="xsl:template[@name='bar']" name="bar">
    Bla bla bla bar
      </xsl:template>

      <xsl:template match="/">
        <xsl:variable name="templateName" select="'bar'"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name=$templateName]"/>
        <xsl:apply-templates select="document('')/*/xsl:template[@name='foo']"/>
      </xsl:template>

    </xsl:stylesheet>

이전에 기여한 것과 유사하게 변수를 사용하여 템플릿의 "호출"을 단순화 할 수 있습니다.

<xsl:variable name="templates" select="document('')/*/xsl:template"/> 

<xsl:apply-templates select="$templates[@name=$templateName]"/>
<xsl:apply-templates select="$templates[@name='foo']"/>

선택 사항에 유의하십시오 <xsl:with-param> 평소처럼 사용할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top