2013-11-21 5 views
6

I有し、このような構造を有する所与のソースXML文書:XSLT - 識別パターンと関連のノードのコンテキストを変更する問題

<?xml version="1.0" encoding="UTF-8"?> 
<sample> 
    <definition> 
    <variable> 
     <name>object01_ID_138368350261919620</name> 
     <value>NUL</value> 
    </variable> 
    <variable> 
     <name>param01_ID_138368350261919621</name> 
     <value>10</value> 
    </variable> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    </definition> 
    <override> 
    <assignment> 
     <name>object01_ID_138368350261919620</name> 
     <path>module01/object01</path> 
    </assignment> 
    <assignment> 
     <name>param01_ID_138368350261919621</name> 
     <path>module01/object01/param01</path> 
    </assignment> 
    <assignment> 
     <name>param02_ID_138368350261919622</name> 
     <path>module01/object01/param02</path> 
    </assignment> 
    </override> 
</sample> 

ソースXMLの特性がある:
<assignment><override>要素内の要素は、<definition>要素内のちょうど1つの<variable>要素に対応します。この1:1の関係は、<name>要素の内容によって確立されます。

変換し、ターゲットXMLの要件は次のとおりです。
<path>要素の内容のパターンに応じて、<override>要素で<assignment>要素の中に、私は新しい<assignment>要素を追加したいです。注目すべき重要な点は、<assignment>要素が主要な情報であることです。したがって、最初に新しい<assignment>要素の<path><name>内容を作成し、これに対応して、対応する新しい<variable>要素と同じ<name>内容と特定の<value>要素を作成し、最後の位置に挿入する必要があります<definition>要素。

<?xml version="1.0" encoding="UTF-8"?> 
<sample> 
    <definition> 
    <variable> 
     <name>param00_ID_138368350261919620</name> 
     <value>NUL</value> 
    </variable> 
    <variable> 
     <name>param01_ID_138368350261919621</name> 
     <value>10</value> 
    </variable> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    <variable> 
     <name>Param03_ID_138368350261919623</name> 
     <value>1000</value> 
    </variable> 
    </definition> 
    <override> 
    <assignment> 
     <name>param00_ID_138368350261919620</name> 
     <path>module01/object01</path> 
    </assignment> 
    <assignment> 
     <name>param01_ID_138368350261919621</name> 
     <path>module01/object01/param01</path> 
    </assignment> 
    <assignment> 
     <name>param02_ID_138368350261919622</name> 
     <path>module01/object01/param02</path> 
    </assignment> 
    <assignment> 
     <name>Param03_ID_138368350261919623</name> 
     <xpath>module01/object01/param03</xpath> 
    </assignment> 
    </override> 
</sample> 

変換のための私のXSL 2.0スタイルシート:たとえば、param03を追加するために、右の結果は次のようになります恒等変換のために
を、私はきめの細かい制御アイデンティティルールを使用することを選びだしてきました、 [Dimitre Novatchev]で推奨されています。 処理param03テンプレートを適用して、新しい<assignment>要素を作成し、その具体的な内容は<path><name>です。そのテンプレート内で、for-each要素を使用して<definition>要素にノードコンテキストを変更し、最後に対応する<name>コンテンツと特定の<value>コンテンツを持つ新しい<variable>要素を追加します。このスタイルシートはSaxon HE 9.5でテストされています。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    exclude-result-prefixes="fo xs fn"> 
    <!-- 
    global declarations ========================================================== 
    --> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <!-- randomid here is just a fake for sake of simplification --> 
    <xsl:variable name="randomid" select="138368350261919623"/> 
    <!-- 
    template - identity ========================================================== 
    --> 
    <xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()[1]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 
    <!-- 
    template - variable assignment =============================================== 
    --> 
    <xsl:template name="variable_assignment"> 
    <xsl:param name="value_node_name"/> 
    <xsl:param name="value_node_path"/> 
    <xsl:message select="'processing: variable assignment'"/> 
    <xsl:message select="concat('applying name: ', $value_node_name)"/> 
    <xsl:message select="concat('applying path: ', $value_node_path)"/> 
    <xsl:call-template name="identity"/> 
    <assignment> 
     <name> 
     <xsl:value-of select="$value_node_name"/> 
     </name> 
     <xpath> 
     <xsl:value-of select="$value_node_path"/> 
     </xpath> 
    </assignment> 
    </xsl:template> 
    <!-- 
    template - processing param03 ============================================= 
    --> 
    <xsl:template match="/sample/override[not(assignment 
       /path[matches(text(), '.*/object01/param03$')])] 
       /assignment[path[matches(text(), '.*/object01$')]]"> 
    <!-- setting params --> 
    <xsl:param name="value_node_name_target"> 
     <xsl:value-of select="concat('Param03_ID', '_', $randomid)"/> 
    </xsl:param> 
    <xsl:param name="value_node_path_target"> 
     <xsl:value-of select="concat(./path, '/param03')"/> 
    </xsl:param> 
    <xsl:param name="value_node_value_target" select="'1000'"/> 
    <!-- processing variable assignment --> 
    <xsl:call-template name="variable_assignment"> 
     <xsl:with-param name="value_node_name" select="$value_node_name_target"/> 
     <xsl:with-param name="value_node_path" select="$value_node_path_target"/> 
    </xsl:call-template> 
    <!-- processing variable definition --> 
    <xsl:for-each select="/sample/definition/*[position()=last()]"> 
     <xsl:message select="'processing: variable definition'"/> 
     <xsl:message select="concat('Here we are: ', .)"/> 
     <xsl:message select="concat('applying name: ', $value_node_name_target)"/> 
     <xsl:message select="concat('applying value: ', $value_node_value_target)"/> 
     <xsl:call-template name="identity"/> 
     <variable> 
     <name> 
      <xsl:value-of select="$value_node_name_target"/> 
     </name> 
     <value> 
      <xsl:value-of select="$value_node_value_target"/> 
     </value> 
     </variable> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

結果として間違ったXMLは次のとおりです。私が得た

<?xml version="1.0" encoding="UTF-8"?> 
<sample> 
    <definition> 
    <variable> 
     <name>object01_ID_138368350261919620</name> 
     <value>NUL</value> 
    </variable> 
    <variable> 
     <name>param01_ID_138368350261919621</name> 
     <value>10</value> 
    </variable> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    </definition> 
    <override> 
    <assignment> 
     <name>object01_ID_138368350261919620</name> 
     <path>module01/object01</path> 
    </assignment> 
    <assignment> 
     <name>param01_ID_138368350261919621</name> 
     <path>module01/object01/param01</path> 
    </assignment> 
    <assignment> 
     <name>param02_ID_138368350261919622</name> 
     <path>module01/object01/param02</path> 
    </assignment> 
    <assignment> 
     <name>Param03_ID_138368350261919623</name> 
     <xpath>module01/object01/param03</xpath> 
    </assignment> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    <variable> 
     <name>Param03_ID_138368350261919623</name> 
     <value>1000</value> 
    </variable> 
    </override> 
</sample> 

問題は次のとおりである:

  1. ノードコンテキストが変更されない状態になります。新しい<variable>要素は最後の位置で<override>要素に追加され、代わりに<definition>要素に追加されます。
  2. さらに、<definition>要素の最後の<variable>要素が<override>要素にコピーされます。それは私が望むものではありません。

ヘルプが必要です。
誰かがアドバイスを受けることができれば本当に感謝しています。上記のように、問題と正しい振る舞いを取り除くためにXSLTを適応させる必要があります。

多くのありがとうございます。

私によって適合あなたが提案したXSLT 2.0、:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fo xs fn"> 
    <!-- 
    global declarations ========================================================== 
    --> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <!-- baserandom here is just a fake for sake of simplification --> 
    <xsl:param name="baserandom" select="138368350261919623"/> 
    <!--MOVED PARAMS FROM ORIGINAL TEMPLATE HERE SO THEY CAN BE USED BY MULTIPLE TEMPLATES --> 
    <!--xsl:param name="value_node_path"--> 
    <!--I LEFT THE PREDICATE BECAUSE IT APPEARS THAT THERE COULD BE MORE THAN ONE override ELEMENT.--> 
    <!--xsl:value-of select="concat(/sample/override[not(assignment/path[matches(text(), '.*/object01/param03$')])] 
      /assignment[1]/path, '/param03')"/> 
    </xsl:param> 
    <xsl:param name="value_node_value" select="'1000'"/--> 
    <!-- 
    template - identity ========================================================== 
    --> 
    <xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()[1]"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 
    <!-- 
    template - definition ======================================================== 
    --> 
    <!--REPLACES THE xsl:for-each THAT PROCESSES THE VARIABLE DEFINITION--> 
    <xsl:template match="definition/*[last()]"> 
    <xsl:param name="value_node_name"/> 
    <xsl:param name="value_node_value"/> 
    <xsl:call-template name="identity"/> 
    <xsl:if test="$value_node_name"> 
     <xsl:message select="'processing: variable definition'"/> 
     <xsl:message select="concat('Here we are: ', .)"/> 
     <xsl:message select="concat('applying name: ', $value_node_name)"/> 
     <xsl:message select="concat('applying value: ', $value_node_value)"/> 
     <variable> 
     <name> 
      <xsl:value-of select="$value_node_name"/> 
     </name> 
     <value> 
      <xsl:value-of select="$value_node_value"/> 
     </value> 
     </variable> 
    </xsl:if> 
    </xsl:template> 
    <!-- 
    template - processing param03 ============================================= 
    --> 
    <xsl:template match="/sample/override[not(assignment/path[matches(text(), '.*/object01/param03$')])] 
     /assignment[path[matches(text(), '.*/object01$')]]"> 
    <!-- name --> 
    <xsl:param name="value_node_name"> 
     <xsl:value-of select="concat('param03_ID', '_', $baserandom)"/> 
    </xsl:param> 
    <!-- path --> 
    <xsl:param name="value_node_path"> 
     <xsl:value-of select="concat(./path, '/param03')"/> 
    </xsl:param> 
    <!-- value --> 
    <xsl:param name="value_node_value" select="'1000'"/> 
    <!-- processing definition --> 
    <xsl:apply-templates select="/sample/definition/*[last()]"> 
     <xsl:with-param name="value_node_name" select="$value_node_name"/> 
     <xsl:with-param name="value_node_value" select="$value_node_value"/> 
    </xsl:apply-templates> 
    <!-- processing assignment --> 
    <xsl:message select="'processing: variable assignment'"/> 
    <xsl:message select="concat('applying name: ', $value_node_name)"/> 
    <xsl:message select="concat('applying path: ', $value_node_path)"/> 
    <xsl:call-template name="identity"/> 
    <assignment> 
     <name> 
     <xsl:value-of select="$value_node_name"/> 
     </name> 
     <path> 
     <xsl:value-of select="$value_node_path"/> 
     </path> 
    </assignment> 
    </xsl:template> 
</xsl:stylesheet> 

(まだ間違った)結果のXML:

<?xml version="1.0" encoding="UTF-8"?> 
<sample> 
    <definition> 
    <variable> 
     <name>object01_ID_138368350261919620</name> 
     <value>NUL</value> 
    </variable> 
    <variable> 
     <name>param01_ID_138368350261919621</name> 
     <value>10</value> 
    </variable> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    </definition> 
    <override> 
    <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
    </variable> 
    <variable> 
     <name>param03_ID_138368350261919623</name> 
     <value>1000</value> 
    </variable> 
    <assignment> 
     <name>object01_ID_138368350261919620</name> 
     <path>module01/object01</path> 
    </assignment> 
    <assignment> 
     <name>param01_ID_138368350261919621</name> 
     <path>module01/object01/param01</path> 
    </assignment> 
    <assignment> 
     <name>param02_ID_138368350261919622</name> 
     <path>module01/object01/param02</path> 
    </assignment> 
    <assignment> 
     <name>param03_ID_138368350261919623</name> 
     <path>module01/object01/param03</path> 
    </assignment> 
    </override> 
</sample> 
+0

"param03を追加する例について..." * - 'param03' *が追加されたどのように* ?一番上に表示されているソースXMLを、あなたが投稿した結果XMLにどのように変換するべきかは、私には分かりません。 – ABach

+0

_param03_の例では、 ''要素を ' '要素内に追加することで、両方のXSLTがうまく機能していることを示したいと思います(コメント_"処理変数割り当て "_の後のコードを参照)。やってみなよ。私が記述した問題は、対応する ''要素を ''要素に追加するために必要な変換の中で生じました(コメント_ "処理後のコード_ _変数定義" _を参照してください。 –

+0

非常に長く冗長であるため、この質問に答えることにユーザーが躊躇していると思います。入力XMLを変更する方法をごく少数の文章で記述してください(ただし、 –

答えて

1

あなたが持っている問題は、そのxsl:for-each ISNです出力コンテキストを変更することはできません。反復のコンテキストを変更するだけです。

xsl:for-each select="/sample/definition/*[position()=last()]を繰り返しているときは、まだassignment(テンプレートマッチ)のコンテキストで出力しています。

definitionのコンテキストから新しいvariableを出力する必要があります。

私はあなたの望むものを生み出すためにあなたのXSLTを修正しました。それは最終的な解決策ではないかもしれませんが、あなたを近づけるはずです。私は、私が変更したことを説明しようとするコメント(すべて大文字)を追加しました。質問があれば教えてください。

修正XSLT 2.0

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    exclude-result-prefixes="fo xs fn"> 

    <!-- 
    global declarations ========================================================== 
    --> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <!-- randomid here is just a fake for sake of simplification --> 
    <xsl:param name="randomid" select="138368350261919623"/> 
    <!--MOVED PARAMS FROM ORIGINAL TEMPLATE HERE SO THEY CAN BE USED BY MULTIPLE TEMPLATES --> 
    <xsl:param name="value_node_name_target"> 
     <xsl:value-of select="concat('Param03_ID', '_', $randomid)"/> 
    </xsl:param> 
    <xsl:param name="value_node_path_target"> 
     <!--I LEFT THE PREDICATE BECAUSE IT APPEARS THAT THERE COULD BE MORE THAN ONE override ELEMENT.--> 
     <xsl:value-of select="concat(/sample/override[not(assignment/path[matches(text(), '.*/object01/param03$')])] 
      /assignment[1]/path, '/param03')"/> 
    </xsl:param> 
    <xsl:param name="value_node_value_target" select="'1000'"/> 

    <!-- 
    template - identity ========================================================== 
    --> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()[1]"/> 
     </xsl:copy> 
     <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 

    <!-- 
    template - variable assignment =============================================== 
    --> 
    <!--MOVED CODE FROM THIS TEMPLATE INTO THE assignment TEMPLATE--> 

    <!--REPLACES THE xsl:for-each THAT PROCESSES THE VARIABLE DEFINITION--> 
    <xsl:template match="definition[../override[not(assignment/path[matches(text(), '.*/object01/param03$')])] 
     /assignment[path[matches(text(), '.*/object01$')]]]/*[last()]"> 
     <xsl:message select="'processing: variable definition'"/> 
     <xsl:message select="concat('Here we are: ', .)"/> 
     <xsl:message select="concat('applying name: ', $value_node_name_target)"/> 
     <xsl:message select="concat('applying value: ', $value_node_value_target)"/> 
     <xsl:call-template name="identity"/> 
     <variable> 
      <name> 
       <xsl:value-of select="$value_node_name_target"/> 
      </name> 
      <value> 
       <xsl:value-of select="$value_node_value_target"/> 
      </value> 
     </variable> 
    </xsl:template> 

    <!-- 
    template - processing param03 ============================================= 
    --> 
    <xsl:template match="/sample/override[not(assignment/path[matches(text(), '.*/object01/param03$')])] 
     /assignment[path[matches(text(), '.*/object01$')]]"> 
     <!-- setting params --> 
     <!--MOVED TEMPLATE PARAMS TO GLOBAL PARAMS--> 
     <!-- processing variable assignment --> 
     <!--REPLACED UNNECESSARY xsl:call-template WITH ACTUAL CODE--> 
     <xsl:message select="'processing: variable assignment'"/> 
     <xsl:message select="concat('applying name: ', $value_node_name_target)"/> 
     <xsl:message select="concat('applying path: ', $value_node_path_target)"/> 
     <xsl:call-template name="identity"/> 
     <assignment> 
      <name> 
       <xsl:value-of select="$value_node_name_target"/> 
      </name> 
      <!--CHANGED FROM xpath TO path (APPEARED TO BE A TYPO)--> 
      <path> 
       <xsl:value-of select="$value_node_path_target"/> 
      </path> 
     </assignment>  <!-- processing variable definition --> 
     <!--THIS IS NOW DONE BY A SEPARATE MATCHING TEMPLATE--> 
    </xsl:template> 
</xsl:stylesheet> 

出力あなたは*と言う

<sample> 
    <definition> 
     <variable> 
     <name>object01_ID_138368350261919620</name> 
     <value>NUL</value> 
     </variable> 
     <variable> 
     <name>param01_ID_138368350261919621</name> 
     <value>10</value> 
     </variable> 
     <variable> 
     <name>param02_ID_138368350261919622</name> 
     <value>100</value> 
     </variable> 
     <variable> 
     <name>Param03_ID_138368350261919623</name> 
     <value>1000</value> 
     </variable> 
    </definition> 
    <override> 
     <assignment> 
     <name>object01_ID_138368350261919620</name> 
     <path>module01/object01</path> 
     </assignment> 
     <assignment> 
     <name>param01_ID_138368350261919621</name> 
     <path>module01/object01/param01</path> 
     </assignment> 
     <assignment> 
     <name>param02_ID_138368350261919622</name> 
     <path>module01/object01/param02</path> 
     </assignment> 
     <assignment> 
     <name>Param03_ID_138368350261919623</name> 
     <path>module01/object01/param03</path> 
     </assignment> 
    </override> 
</sample> 
+0

あなたの解決策はありますが、あなたの解決策はまだ解決していません。常に最先端の仕事でなければなりません。つまり、サンプルparam03の割り当ての一致ルールがtrue(偽である可能性もあります)と評価された場合、個々のID(インクリメント基底)処理に基づいて処理が行われなければなりません。ターゲットXML "*。したがって、私の意見では、定義の作成は、代入(例えばparam03)を作成することによってパラメータ化されなければなりません。しかし、その後私の問題は戻っています。 –

+0

'assignment'のために行う必要のあるテストは、' definition'に対しても行うことができます。私は '定義'テンプレートに述語を追加しました。 XSLTのバージョンを変更しただけなので、IDの増分を追加しようとはしませんでした。それが必要な場合は、後でもっと時間があるときに見てみることができます。 –

+0

ありがとうございます。私は、割り当てと定義の間に強い依存関係があることを強調するために、IDで事実を述べました。定義テンプレートに追加された述語は、あなたが提案した方法です。しかし、私にとっては、実行時に同じIDを両方に提供する方法が明確ではありません。上記(*私が適応させたあなたが提案したXSLT 2.0)を参考にして、あなたが提案したXSLTをどのように適合させたかを見てください。残念ながら、それは同じ間違ったXMLを生成します。 –

関連する問題