2017-05-24 15 views
1

一般 JavaScriptを含むXMLを変更しようとしています。 JavaScriptがページトップレベルの1つを参照している場合は、トップレベルの階層レベルを追加したいと思います。XSLT:グローバル変数を属性値に設定する

細目 私は新しいトップレベル(formNameフォーム)を見つけると、彼らはページトップレベル(ページ名とsubPageNames)で始まる割り当てを持っている場合、スクリプトに追加します。私はXMLSpyでこれを実行しようとしましたが、変数formNameに値を設定することさえできません。これを解決する最善の方法は何ですか?

私の例のXML:

<?xml version="1.0" encoding="UTF-8"?> 
<template> 
    <subform name="formABC"> 
    <pageSet> 
     <pageArea name="Page1"> 
      <subform> 
       <field> 
        <event> 
         <script>this.rawValue = SubPageA.subhuvud.namn.rawValue;</script> 
        </event> 
       </field> 
       <field> 
        <event> 
         <script>this.rawValue = not_this.rawValue;</script> 
        </event> 
       </field> 
      </subform> 
     </pageArea> 
     <pageArea name="Page2"> 
      <field> 
       <event> 
        <script>this.rawValue = SubPageK.subhuvud.namn.rawValue;</script> 
       </event> 
      </field> 
      <area> 
       <field> 
        <event> 
         <script>this.rawValue = Page1.subhuvud.namn.rawValue;</script> 
        </event> 
       </field> 
       <field> 
        <event> 
         <script>this.rawValue = other.rawValue;</script> 
        </event> 
       </field> 
      </area> 
     </pageArea> 
    </pageSet> 
    <subform name="SubPageA"> 
    </subform> 
    <subform name="SubPageK"> 
    </subform> 
    </subform> 
</template> 

私の現在のXSL:私が求めて

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl" 
xmlns:xdp="http://ns.adobe.com/xdp/"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:variable name="formName"  select="/xdp:xdp/template/subform/@name"/> 
<xsl:variable name="pageNames" select="/xdp:xdp/template/subform/subform/@name"/> 
<xsl:variable name="subPageNames" select="/xdp:xdp/template/subform/pageSet/pageArea/@name"/> 
<xsl:variable name="allPageNames" select="concat($pageNames, $subPageNames)"/> 

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

<!--Rewite Javascript--> 
<!--Insert formname in front of page that is first.--> 
<xsl:template match="//script"> 
    <xsl:variable name="match" select="exsl:node-set($allPageNames)[contains(current(), .)]"/> 
    <xsl:choose> 
     <xsl:when test="$match">            <!--this.rawValue = Page1.subhuvud.namn.rawValue;--> 
      <xsl:value-of select="substring-before(., $match)"/>    <!--this.rawValue = --> 
      <xsl:value-of select="$formName"/>         <!--formABC--> 
      <xsl:value-of select="'.'"/>          <!--.--> 
      <xsl:value-of select="$match"/>          <!--Page1--> 
      <xsl:value-of select="substring-after(., $match)"/>     <!--.subhuvud.namn.rawValue;--> 
     </xsl:when>                <!--this.rawValue = formABC.Page1.subhuvud.namn.rawValue;--> 
     <xsl:otherwise> 
      <xsl:copy/> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

出力:バインド変数の値に関しては

<?xml version="1.0" encoding="UTF-8"?> 
<template> 
<subform name="formABC"> 
    <pageSet> 
     <pageArea name="Page1"> 
      <subform> 
       <field> 
        <event> 
         <script>this.rawValue = formABC.SubPageA.subhuvud.namn.rawValue;</script> 
        </event> 
       </field> 
       <field> 
        <event> 
         <script>this.rawValue = not_this.rawValue;</script> 
        </event> 
       </field> 
      </subform> 
     </pageArea> 
     <pageArea name="Page2"> 
      <field> 
       <event> 
        <script>this.rawValue = formABC.SubPageK.subhuvud.namn.rawValue;</script> 
       </event> 
      </field> 
      <area> 
       <field> 
        <event> 
         <script>this.rawValue = formABC.Page1.subhuvud.namn.rawValue;</script> 
        </event> 
       </field> 
       <field> 
        <event> 
         <script>this.rawValue = other.rawValue;</script> 
        </event> 
       </field> 
      </area> 
     </pageArea> 
    </pageSet> 
    <subform name="SubPageA"> 
    </subform> 
    <subform name="SubPageK"> 
    </subform> 
    </subform> 
    </template> 
+0

私が最初に気づくのは、あなたの変数バインドに 'SELECT'式はルート要素が' 'になることを想定していることですが、それはそれが何であるかではありませんあなたの入力例では。 –

+0

私はstackoverflowのためにそれを単純化する前に、元のXML構造の残りのthats、はい。 –

答えて

1

、私は自分に拡大しますselectの表現が/xdp:xdpに根ざしていることを指摘してコメントしてくださいrはあなたの入力ファイルの中の何かにマッチするので、関連する変数の値は常に空のノードセットになります。あなたは、単にその要素を除去することにより、(例えば、入力に関して)これを修正することができるはずです。

<xsl:variable name="formName" select="/template/subform/@name"/> 

concat()を必要とするため、次に、私はあなたが変数allPageNamesの値を形成するメカニズムが働くことができないことを確認します文字列引数ですが、ノードセットを提供しようとしています。ノアは、文字列にノードセットを変換するストリングに設定されたノードの変換

  1. はあなたに最初ノード(のみ)
  2. の文字列値を取得しますので、あなたが形成しようとしている、正しいことを行います最後に、元の文字列を抽出することができなくなるはずの連結されていない連結です。
  3. 実際に値を使用する場合は、その値をノードセットに変換します。そのため、最初にノードセットとして値を生成するほうがよいでしょうか?

XPathには、この変数の値の式で使用できるノードセット結合演算子|があります。 allPageNamesがすでにノード集合であるので、例えば

<xsl:variable name="pageNames" select="/template/subform/subform/@name"/> 
<xsl:variable name="subPageNames" select="/template/subform/pageSet/pageArea/@name"/> 
<xsl:variable name="allPageNames" select="$pageNames | $subPageNames"/> 

は今、あなたは、(あなたが質問に提示何のために)EXSLを必要としません。

しかし、これでは不十分です:scriptテンプレートの変数matchに問題があります。 は別の文字列関数であり、ノードセットを渡そうとしているため、割り当て内のselect式は機能しません。さらに、それが述語の内部にある場合は、ではなく、であると評価されるノードに評価されます。希望するように、<script>要素が変換されます。いずれにしても、実行しようとしているように見えるテストでは、誤検出が起こりやすくなります。

私は別のアプローチを提案します。まず、テストするオブジェクトの名前を特定します。

<xsl:variable name="topObject" 
    select="normalize-space(substring-before(concat(substring-after(., '='), '.'), '.'))"/> 

は、あなたが選択した名前が$allPageNamesによって記載されているものの中にあるかどうかをテストできることを行ってた:これは、あなたがそれを説明するように、コンテキストノードとしてscript要素で処理する場合、これは、あなたの目的と一致している可能性があるように見えますこのテスト式を介してノードセット:$allPageNames[. = $topObject]。全体的に、scriptテンプレートは次のようになります。

<xsl:template match="script"> 
    <!-- assumed: this element has text-only content --> 
    <xsl:variable name="topObject" 
     select="normalize-space(substring-before(concat(substring-after(., '='), '.'), '.'))"/> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:choose> 
     <xsl:when test="$allPageNames[. = $topObject]"> 
     <xsl:value-of select="substring-before(., $topObject)"/> 
     <xsl:value-of select="$formName"/> 
     <xsl:text>.</xsl:text> 
     <xsl:value-of select="$topObject"/> 
     <xsl:value-of select="substring-after(., $topObject)"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="text()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:copy> 
</xsl:template> 
+0

これは素晴らしいです!あなたがこれを説明するために努力してくれてありがとう! /Björn –

+0

concat()関数は何をしていますか?私の理解では、それはsubstring-before()によって削除されるドットを追加しています。 –

+0

@Björn、それはまさにそれがやっていることです。これは元の文字列に ''。 ''がない場合に便利です。 'substring-before()'に直接渡された場合、結果は空文字列になりますが、このように文字列全体になります。開始文字列にすでに ''。 ''が含まれている場合、全体的な結果は '' concat()がない場合と同じになります。 –

関連する問題