4

XSL を適用し、それを上位バージョンの別の XML に変換する必要があるこの入力 XML があります。V3としましょう。したがって、入力 XML はバージョン V1 です。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:NS1="http://www.test1/Error/v1"
      xmlns:NS2="http://www.test1/Error/schema/SCRIPT"
      xmlns:tns="http://www.test1/webservice/Service/v1"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <tns:Sample>
         <NS2:Message release="006" version="010">
            <NS2:Header>
              <NS2:TestMessage>1</NS2:TestMessage>
              </NS2:Header>
            <NS2:Body>
               <NS2:SampleTx>
                  <NS2:Element1>
                     <NS2:IdName>
                        <NS2:ID>
                           <NS2:IDValue>114</NS2:IDValue>
                         </NS2:ID>
                     </NS2:IdName>
                  </NS2:Element1>
                  </NS2:SampleTx>
            </NS2:Body>
         </NS2:Message>
      </tns:Sample>
   </soapenv:Body>
</soapenv:Envelope>

私が適用しているXSLは

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:djh="http://www.test1/webservice/Service/v1"
    xmlns:NS1="http://www.test1/Error/v1"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <xsl:output indent="yes"/>

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

    <xsl:template match="djh:*">
        <xsl:element name="{name()}" namespace="http://www.test1/webservice/Service/v3">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>  
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>      
    </xsl:template>

</xsl:stylesheet>

そして私が得る出力は

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <tns:sendCancelRx xmlns:tns="http://www.test1/webservice/Service/v3">
         <NS2:Message release="006" version="010"
               xmlns:NS2="http://www.ncpdp.org/schema/SCRIPT">
            <NS2:Header>
             <NS2:TestMessage>1</NS2:TestMessage>
             </NS2:Header>
            <NS2:Body>
               <NS2:SampleTx>
              <NS2:Element1>
                 <NS2:IdName>
                    <NS2:ID>
                       <NS2:IDValue>114</NS2:IDValue>
                   </NS2:ID>
                 </NS2:IdName>
              </NS2:Element1>
              </NS2:SampleTx>
            </NS2:Body>
         </NS2:Message>
      </tns:sendCancelRx>
   </soapenv:Body>
</soapenv:Envelope>

からすべての名前空間宣言を取り除きますxmlns:NS1="http://www.test1/Error/v1" xmlns:NS2="http://www.test1/Error/schema/SCRIPT" xmlns:tns="http://www.test1/webservice/Service/v1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

そして、私が望む出力は

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:NS1="http://www.test1/Error/v3"
      xmlns:NS2="http://www.test1/Error/schema/SCRIPT"
      xmlns:tns="http://www.test1/webservice/Service/v3"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <tns:Test>
         <NS2:Message release="006" version="010">
            <NS2:Header>
               <NS2:TestMessage>1</NS2:TestMessage>
              </NS2:Header>
            <NS2:Body>
               <NS2:SampleTx>
          <NS2:Element1>
             <NS2:IdName>
                <NS2:ID>
                   <NS2:IDValue>114</NS2:IDValue>
               </NS2:ID>
             </NS2:IdName>
          </NS2:Element1>
          </NS2:SampleTx>
            </NS2:Body>
         </NS2:Message>
      </tns:Test>
   </soapenv:Body>
</soapenv:Envelope>

私の XSL に欠けているものを教えていただければ幸いです。

4

3 に答える 3

2

xsl:element name="{name()}"との違いは、名前空間宣言xsl:copyをコピーすることですが、コピーしないことです。したがって、それらを保持したい場合に使用してください。xsl:copyxsl:elementxsl:copy

于 2013-06-15T07:26:40.517 に答える
2

次の XSLT は、すべての名前空間宣言 (使用済みおよび未使用) を保持し、tnsnamespace-uri を に変更しhttp://www.test1/webservice/Service/v3ます。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:djh="http://www.test1/webservice/Service/v1"
    xmlns:tns="http://www.test1/webservice/Service/v3"
    xmlns:NS1="http://www.test1/Error/v1"
    xmlns:NS2="http://www.test1/Error/schema/SCRIPT"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <xsl:output indent="yes"/>

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

    <xsl:template match="djh:*">
        <!--reconstruct an element using the new v3 namespace,
            but use the same namespace-prefix "tns"-->
        <xsl:element name="tns:{local-name()}" 
                     namespace="http://www.test1/webservice/Service/v3">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>  
    </xsl:template>

    <xsl:template match="*">
        <xsl:element name="{name()}" namespace="{namespace-uri()}">    
            <!--copy all of the namespace declarations, 
                except for "tns" - which is v1 in the source XML -->
            <xsl:copy-of select=
                    "namespace::*
                    [not(name()='tns')]"/> 
            <!--copy the namespace declaration for "tns" from the XSLT,
                which is v3, and add it to the element-->
            <xsl:copy-of select=
                "document('')/*/namespace::*[name()='tns']"/>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Saxon 9.x では次の出力が生成されます (Xalan では未使用の名前空間は保持されませんが、これは明らかにXALANJ-1959によるものです)。

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:NS1="http://www.test1/Error/v1"
                  xmlns:NS2="http://www.test1/Error/schema/SCRIPT"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:tns="http://www.test1/webservice/Service/v3">
    <soapenv:Body>
        <tns:Sample>
            <NS2:Message release="006" version="010">
                <NS2:Header>
                    <NS2:TestMessage>1</NS2:TestMessage>
                </NS2:Header>
                <NS2:Body>
                    <NS2:SampleTx>
                        <NS2:Element1>
                            <NS2:IdName>
                                <NS2:ID>
                                    <NS2:IDValue>114</NS2:IDValue>
                                </NS2:ID>
                            </NS2:IdName>
                        </NS2:Element1>
                    </NS2:SampleTx>
                </NS2:Body>
            </NS2:Message>
        </tns:Sample>
    </soapenv:Body>
</soapenv:Envelope>
于 2013-06-16T12:37:20.630 に答える
2

これらの名前空間プレフィックス宣言をすべて削除していると言う理由がわかりません。不要なものは取り除きますが、NS2and tns(and soapenv) の宣言は残します。

使用されていない名前空間プレフィックスを宣言しても、何も達成されません。なんで気にするの?出力 XML のすべての要素が正しい名前空間にある。これは、下流の XML コンシューマにとって重要なことです。

NS2(名前空間 URI の変更は、解決しようとしている問題の一部ではないと想定しています。)

XSLT は、出力 XML の各要素が適切な名前空間にあることを確認します。それ以外は、出力 XML のセマンティクスに影響しないため、名前空間プレフィックスが宣言されている場所を細かく制御することはできません。

于 2013-06-15T02:16:37.887 に答える