2012-01-24 21 views
6

XSLTに条件付きインクルードを実行したいが、xsl:includeはトップレベル要素です。 xsl:ifまたはxsl:chooseはテンプレート内でのみ使用できます。外部ファイルの条件付きインクルードを許可するハックや回避策はありますか?私はdocument()関数を使用しようとしましたが、おそらくそれが "有効"になるいくつかの規則のセットに従っていないため、外部ファイルを読み込めません。外部ファイルのXSLT条件付きインク

私の外部XMLファイルは、xsltコードの断片の束です。メインXSLTファイルの変数の値に応じて、外部ファイルの対応するコードは、(CまたはPHPの条件付きインクルードのように) "コピー/貼り付け"する必要があります。

私のメインのXSLTファイルの流れは次のように進めるべき

$configurationMode 
if ($configurationMode = Standard) { xsl:include="standard.xml" } else { xsl:include="alt.xml" } 

もちろん、私は、単に上記のようにそれを行うことができない、ハックや回避策がある場合はそれゆえ、なぜ私が求めています。

答えて

3

私が理解しているように、XMLパーザが解析してスタイルシートをコンパイルするとき、「インクルード」が発生します。これは、インクルードが処理される前に論理式や式の評価が行われないことを意味し、したがって、条件付きでインクルードする方法はありません。条件付き動作をスタイルシートの外で行う必要があります。

は、特にこのhttp://www.dpawson.co.uk/xsl/sect2/N4760.html#d6065e100

を見ては、マイク・ケイの助けによってこのコメントんがあります:これは回数を

提起されています。以前のスレッドでは、ユーザーが スタイルシートGを汎用的に記述して、 特殊用途スタイルシートAまたはBを条件付きで使用して特殊化しようとしていたという結論に達しました。この要件を満たす方法は ですあなたは 変換を開始するときにAとBに条件付きで主なスタイルシートとしてAまたはBを選択します。

6

これはXSLT 1.0で行うことができず、use-when属性を用いたXSLT 2.0(非常に限られた範囲で)行うことができます。

xsl:includeまたはxsl:importディレクティブの動的変更を実現する非xslt方法があります。

そのような方法の一つは常にXmlDocumentとしてXSLTスタイルシートをロードし、所望の値にhref属性を設定するために、アクセスおよび属性の変更のために利用可能なDOMメソッドを使用することです。次に、このメモリ内で変更されたXMLDocumentに含まれるXSLTスタイルシートから変換を開始します。

3

構造を反転させてみてください:2つの特別目的モジュールpink.xslとblue.xslと汎用モジュールbaby.xslがある場合は、pink.xslまたはblueのいずれかをインポート/インクルードしようとするのではなく、 xslをbaby.xslに変換する代わりに、最上位のエントリスタイルシートとしてpink.xslまたはblue.xslを使用し、それぞれに2つのbaby.xslをインポートします。それは、それが使用されるように設計された方法です、それはハックまたは回避策です。

また、「外部xmlファイルはxsltコードフラグメントの束です」とすると、XSLTの変換を使用して、これらのフラグメントからスタイルシートを別のステップとしてアセンブルする方がよい場合がありますxsl:include/xsl:importを使用するのではなく、

0

すでに述べたことに加えて、補足ファイルを(XSLTファイルではなく)プレーンなコンテンツ提供XMLファイルにすることが考えられます。そうすれば、XPathのdocument()関数(コンパイル時ではなく実行時に評価される)を使ってそれらを含めることができます。

ロードされたXMLドキュメントの内容に基づいて、変換の動作を変更できます。ただし、含まれるドキュメントには実行可能なXSLTフラグメントを提供することはできません。

これはソリューションであるかどうかによって異なります。追加のドキュメントが変換のコントロールフローに強い影響を与える場合は、単純にXMLで定義する必要はありません。 - XSLTのようなものを実装します。しかし、ドキュメントが構成ファイルの一種として役立つときには、それらを純粋なXMLと考えることが考えられます。

document()で問題が発生している場合は、ファイルでXMLバリデーターを使用してください。エラーは、ファイルが有効なXMLではないことを意味します。

0
<xsl:variable name="CONDITIONAL" select="ELEMENT/CONDITION"/> 
<xsl:variable name="DOCUMENTNAME" select="document(concat($CONDITIONAL,'-DOCUMENT.xml'))/ELEMENT"/> 

この例は、外部ファイルを条件付きで使用した例です。 XSLが変数として使用する基本XMLにフラグを設定して、テンプレートにプルする別のファイルの名前を指定しました。その変数が私の場合のように定義されると、他のXMLデータを生成された出力に引き出すためにそれを使用します。 concatコマンドは、データをまとめて強制的にファイル名にします。

だから、私は外部のXMLファイルから情報を得たいときは、外部データを参照するために '$ DOCUMENTNAME'を使用します。

1

これがあなたのシナリオに当てはまるかどうかはわかりませんが、とにかくこれを投げ捨てます。

私は過去に同様のことをしましたが、条件付きインクルードの代わりに、xsl:whenの評価に基づいて2つのファイルのいずれかのテンプレートを呼び出します。あなたのケースでテンプレートを使用したくない場合は、この回答を無視してください。例えば

、「親」XSLTファイルがroot.xsltと呼ばれ言うと、2つの条件付きで、使用したものは、child1.xsltchild2.xsltです。 という状態のノードの値に対して条件付きロジックを実行したいとします。。値が "CURRENT"の場合は、というテンプレートをchild1.xsltのisCurrentと呼びます。そうでない場合はという名前のテンプレートを呼び出します.NotCurrentはchild2.xsltです。簡潔にするために、それぞれのケースで私はテンプレートにルートノードとすべての子を渡すだけです。

それは次のようになりたい:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:import href="child1.xslt"/> 
    <xsl:import href="child2.xslt"/> 

    <xsl:template match="/"> 
     <xsl:choose> 
     <xsl:when test="rootNode/status = 'CURRENT'"> 
      <!-- template isCurrent defined in child1.xslt --> 
      <xsl:apply-templates select="rootNode" mode="isCurrent" /> 
     </xsl:when> 
     <xsl:otherwise> 
      <!-- template isNotCurrent defined in child2.xslt --> 
      <xsl:apply-templates select="rootNode" mode="isNotCurrent" /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

希望は、これは、少なくとも少しのに役立ちます。

0

static parametersを追加すると、XSLT 3.0でこれが可能になりました。静的パラメータは属性のxsl:includeで使用できます。

今、私たちはfalse()のデフォルト値でパラメータを宣言してから、我々は、実行時に必要なものを上書きすることができます...ここで

<xsl:param name="someparam" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 
<xsl:include href="include_me.xsl" use-when="$someparam"/> 

は(もでテストSaxon-HE V9.7でテストの完全実施例でありますSaxon-PE 9.5)。

XML入力(のtest.xml)

<doc> 
    <foo/> 
</doc> 

メインXSLT 3.0(test_main.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="inc1" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 
    <xsl:param name="inc2" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 

    <xsl:include href="test_inc1.xsl" use-when="$inc1"/> 
    <xsl:include href="test_inc2.xsl" use-when="$inc2"/> 

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

可能ファーストは含まXSLT 3.0(test_inc1.xsl)

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

    <xsl:template match="foo"> 
    <xsl:copy>INCLUDE FILE 1!!!</xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

第二の可能な含まXSLT 3.0(test_inc2.xsl)

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

    <xsl:template match="foo"> 
    <xsl:copy>INCLUDE FILE 2!!!</xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

コマンドライン(trueに設定inc2

java -cp "saxon9he.jar" net.sf.saxon.Transform -s:"test.xml" -xsl:"test_main.xsl" inc2="true" 

出力

<doc> 
    <foo>INCLUDE FILE 2!!!</foo> 
</doc> 
0

がありますXSLT 2.0のuse-when機能を使用してファイルを条件付きでインクルードする方法があります。

私の場合、私は、Javaを使用していますようにあなたは、実行時にアプリケーションを通過する一つのシステムプロパティを作成する必要があるので、私は自分のアプリケーションを実行するためのコマンドを使用して、「デバッグ」プロパティを作成しました:

java -DDebug=yes myAppPath 

XSLTでは、このプロパティを使用して条件ファイルを組み込みます。例えば、

<xsl:include href="file1.xslt" use-when="system-property('DEBUG') = 'yes'"/> 
<xsl:include href="file2.xslt" use-when="system-property('DEBUG') != 'yes'"/> 

そうです。

尋ねられるシナリオに合っているかどうかわかりませんが、はい、XSLT 2.0でそれを行う方法があります。 XSLT 3.0では、ローカル変数のサポートも追加されています。だから、ローカル変数を使って簡単にこれを行うことができます。

おかげで、ハッピー はコーディング

関連する問題