はい、これは非常に強力な手法であり、私は「空白を埋める」と呼んでいます。
これは非常に短い例です:
スケルトン1:
<html xmlns:gen="my:tranform-generated">
<body>
<h1>Hi <gen:fname/>!</h1>
</body>
</html>
スケルトン2:
<html xmlns:gen="my:tranform-generated">
<body>
<h1>Hi <gen:fname/> <gen:lname/>!</h1>
You are <gen:age/> years old.
</body>
</html>
XSLT変換は、「使用するスケルトン」のUriを外部パラメーターとして渡され、特別な名前の要素(名前は特別な名前空間「my:tranform-」にある)を除いて、すべてのノードを「そのまま」コピーします。生成された」)。これらは、XSLT変換でそれらに一致するテンプレートの結果に置き換えられます。
このような変換の例を次に示します。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gen="my:tranform-generated" exclude-result-prefixes="gen">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pSkeleton" select="'file:///c:/temp/delete/Skeleton1.xml'"/>
<xsl:variable name="vData" select="/"/>
<xsl:template match="/">
<xsl:apply-templates select="document($pSkeleton)/*"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="namespace::*[not(. = 'my:tranform-generated')]"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="*[namespace-uri()='my:tranform-generated']">
<xsl:value-of select="$vData/*/*[name() = local-name(current())]"/>
</xsl:template>
</xsl:stylesheet>
この変換がこのXMLドキュメントに適用される場合:
<person>
<fname>John</fname>
<lname>Smith</lname>
<age>25</age>
</person>
(Skeleton1.xmlを使用して)必要な正しい結果が生成されます。
<html>
<body>
<h1>Hi John!</h1>
</body>
</html>
同じ変換が同じXMLドキュメントに適用されている$pSkeleton
が、それに渡された外部パラメーターの値がである"file:///c:/temp/delete/Skeleton2.xml"
場合、再び必要な結果(フォーマットされたSkeleton2)が得られます。
<html>
<body>
<h1>Hi JohnSmith!</h1>
You are 25 years old.
</body>
</html>
更新:
OPからの要求に応じて、反復を処理する方法の例を次に示します。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:gen="my:tranform-generated" exclude-result-prefixes="gen">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pSkeleton" select="'file:///c:/temp/delete/Skeleton3.xml'"/>
<xsl:variable name="vData" select="/"/>
<xsl:template match="/">
<xsl:apply-templates select="document($pSkeleton)/*"/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="namespace::*[not(. = 'my:tranform-generated')]"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
<xsl:template match="*[namespace-uri()='my:tranform-generated']">
<xsl:value-of select="$vData/*/*[name() = local-name(current())]"/>
</xsl:template>
<xsl:template match="gen:context" priority="2">
<xsl:apply-templates>
<xsl:with-param name="pContext"
select="$vData/*/*[name()=current()/@select][1]"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="gen:iterate" priority="2">
<xsl:param name="pContext"/>
<xsl:variable name="vDelim" select="string(@delimiter)"/>
<xsl:for-each select="$pContext/*[name()= current()/@select]">
<xsl:if test="not(position()=1)"><xsl:copy-of select="$vDelim"/></xsl:if>
<xsl:copy-of select="node()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Skeleton3.xml:
<html xmlns:gen="my:tranform-generated">
<body>
<h1>Hi <gen:fname/> <gen:lname/>!</h1>
You are <gen:age/> years old.
Education:
<gen:context select="education">
<gen:iterate select="degree" delimiter=", "/>
</gen:context>
</body>
</html>
上記の変換がこのXMLドキュメントに適用される場合:
<person>
<fname>John</fname>
<lname>Smith</lname>
<age>25</age>
<education>
<degree>MSc. Biology</degree>
<degree>MBa.</degree>
<degree>PhD. Computer Science</degree>
</education>
</person>
必要な正しい結果が生成されます:
<html>
<body>
<h1>Hi JohnSmith!</h1>
You are 25 years old.
Education:
MSc. Biology, MBa., PhD. Computer Science
</body>
</html>