문제
가능한지 모르겠지만 어떻게 해야할지 궁금합니다 ...
다음 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 :
(html) at :
http://conferences.idealliance.org/extreme/html/2003/novatchev01/eml2003novatchev01.html
"XSLT 2.0 및 FXSL을 사용한 고차 기능 프로그래밍"(PDF) at :
(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>
평소처럼 사용할 수 있습니다.