1

サンプル XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xslnsv="http://sample2.1">
<xsl:output method="xml" indent="yes"/>

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

<xsl:template match="//xslnsv:Activity">
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:if test="not(@IsForCompensation) 
      and (./xslnsv:IsForCompensationSpecified)">
      <xsl:attribute name="IsForCompensation">
        <xsl:value-of 
          select="./xslnsv:IsForCompensationSpecified" />
      </xsl:attribute>
    </xsl:if>
    <xsl:apply-templates
      select="@*|node()[local-name() 
        != 'IsForCompensationSpecified']" />
  </xsl:copy>
</xsl:template>    
</xsl:stylesheet>

ここに名前空間 xmlns:xslnsv="http://sample2.2" があります。同じ名前空間を持つ xml がある場合に機能します。

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://sample2.2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a">          
          <IsForCompensationSpecified
            >false</IsForCompensationSpecified>
        </Activity>
        <Activity Id="39c5b8d8" Name="Task 1">
          <IsForCompensationSpecified 
            >true</IsForCompensationSpecified>
        </Activity>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes />
</Package>

出力を次のように生成します。

<?xml version="1.0"?>
<Package xmlns="http://sample2.2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d267d-e1ed-4616-adfb-d24d6844f775"
                     Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a-0a01-4d76-9b3b-413ffb3c7a74"    
                  IsForCompensation="false"/>
        <Activity Id="39c5b8d8-9a72-40d1-b3e4-8cd973ccdf03" 
                  Name="Task 1" 
                  IsForCompensation="true"/>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes/>
</Package>

しかし、問題は次のとおりです。名前空間が異なる xml がいくつかあります。例: http://sample2.1 名前空間が異なるサンプル xml

<?xml version="1.0"?>
<Package xmlns="http://sample2.1" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d267d-e1ed-4616-adfb-d24d6844f775" 
                     Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a-0a01-4d76-9b3b-413ffb3c7a74" 
                  IsForCompensation="false"/>
        <Activity Id="39c5b8d8-9a72-40d1-b3e4-8cd973ccdf03" 
                  Name="Task 1" 
                  IsForCompensation="true"/>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes/>
</Package>

それでは、正しい出力がありません。

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://sample2.1" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <ElementAtLevel1>
    <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
      <Activities>
        <Activity Id="ef84125a">
          <IsForCompensationSpecified
            >false</IsForCompensationSpecified>
        </Activity>
        <Activity Id="39c5b8d8" Name="Task 1">
          <IsForCompensationSpecified
            >true</IsForCompensationSpecified>
        </Activity>
      </Activities>
    </ElementAtLevel2>  
  </ElementAtLevel1>
  <ExtendedAttributes />
</Package>

その場で名前空間を変更するために xslt を変更しました。新しい変更を加えた xslt のサンプル

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xslnsv="http://sample2.2" >

  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="vUrl" select="'http://sample2.2'"/>

  <xsl:template match="*[namespace-uri()='http://sample2.1']">
    <xsl:element name="{name()}" namespace="{$vUrl}">
      <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
    </xsl:element>
  </xsl:template> 
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
 <xsl:template match="//xslnsv:Activity">
   <xsl:copy>
     <xsl:copy-of select="@*" />
     <xsl:if test="not(@IsForCompensation) 
                   and (./xslnsv:IsForCompensationSpecified)">
       <xsl:attribute name="IsForCompensation">
         <xsl:value-of 
           select="./xslnsv:IsForCompensationSpecified" />
       </xsl:attribute>
     </xsl:if>
     <xsl:apply-templates select="@*
       |node()[local-name() != 'IsForCompensationSpecified']" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

名前空間を変更することはできますが、名前空間を変更した後に要素を選択することはできません。ソースxmlから古い名前空間、つまり2.1を参照している可能性があります

しかし、まだ正しい出力が得られません。私は次の出力を得ています。

<?xml version="1.0"?>
 <Package xmlns="http://sample2.1" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <ElementAtLevel1>
 <ElementAtLevel2 Id="cf9d2" Name="Pool 1">    
 <Activities>
 <Activity Id="ef84125a">          
 <IsForCompensationSpecified>false</IsForCompensationSpecified>
 </Activity>
 <Activity Id="39c5b8d8" Name="Task 1">
 <IsForCompensationSpecified>true</IsForCompensationSpecified>
 </Activity>
 </Activities>
 </ElementAtLevel2>  
 </ElementAtLevel1>
 <ExtendedAttributes/>
 </Package>
4

1 に答える 1

1

[OPの質問の改訂に照らして改訂。]

私があなたを正しく理解していれば、ローカル名アクティビティを持つ名前空間http://sample2.1の要素が入力で検出された場合、(1) を持つテンプレートがmatch="*[namespace-uri()='http://sample2.1']"それに一致し、それを名前空間http://に移動することを期待しています。 sample2.2、次に (2) のテンプレートが起動しmatch="//xslnsv:Activity"ます。それは正しい理解ですか?

もしそうなら、ここには2つの問題があります。

まず、名前空間を変更するテンプレートは、名前空間http://sample2.2に新しい要素ノードを生成しますが、表示するコードには、その新しい要素ノードにテンプレートを適用しようとするものは何もありません。

2 つ目の問題は、XSLT 1.0 テンプレートが入力ドキュメント内の要素のみに一致することです。スタイルシートによって構築されたノードと一致せず、一致できません。これは、XSLT 1.0 と XSLT 2.0 の大きな違いの 1 つです。XSLT 1.0 の一般的な拡張により、作成されたノードをテンプレートと照合できます。試してみたい場合は、ノードセット拡張に関する情報を探してください。

より簡単な解決策は、スタイルシートを 2 つに分割することです。1 つは古い名前空間から新しい名前空間に要素を移動するためのもので、もう 1 つは新しい名前空間の要素を処理するためのものです。

(結果を再現できないことにも注意してください。入力に対して指定したスタイルシートを実行すると、名前空間http://sample2.1ではなく、名前空間http ://sample2.2に出力が得られます. コピー/貼り付けエラーの被害者だったと思います。)

于 2013-06-05T16:02:50.950 に答える