0

xsl 変換に問題があります。期待した結果が得られず、何が問題なのかわかりません。問題は名前空間に関連していると思います。手伝って頂けますか?

これは、私のサービスが受け取る xml です。多値要素をいくつかの新しいノードに分離したいと考えています。

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap-env:Header/>
   <soap-env:Body>
      <testService facade="Test" xmlns="http://new.webservice.namespace">
         <input>
            <Data1>Data 1</Data1>
            <Data2>Data 2</Data2>
            <ParamResponses>
               <ParamResponse>
                  <Name>DATAONE</Name>
                  <ValParam>Text 1</ValParam>
               </ParamResponse>
               <ParamResponse>
                  <Name>DATATWO</Name>
                  <ValParam>Text 2</ValParam>
               </ParamResponse>
               <ParamResponse>
                  <Name>MULTIVALUED</Name>
                  <ValParam>001</ValParam>
                  <ValParam>002</ValParam>
               </ParamResponse>
               <ParamResponse>
                  <Name>DATATHREE</Name>
                  <ValParam>Text 3</ValParam>
               </ParamResponse>
            </ParamResponses>
         </input>
      </testService>
   </soap-env:Body>
</soap-env:Envelope>

これは私が適用しているxsltです

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@facade">
        <xsl:attribute name="facade">
               <xsl:text>FacadeReplaced</xsl:text>
            </xsl:attribute>
    </xsl:template>
   <xsl:template match="input/ParamResponses">
      <ParamResponses>
         <xsl:for-each select="ParamResponse[Name!='MULTIVALUED']">
            <ParamResponse>
               <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
            </ParamResponse>
         </xsl:for-each>
      </ParamResponses>
      <MultiValueParamResponses>
         <MultiValueParamResponse>
            <Name>MULTIVALUED</Name>
           <xsl:variable name="items" select="//input/ParamResponses/ParamResponse[Name='MULTIVALUED']/ValParam"/>
            <ValueList>
               <xsl:for-each select="$items">
                  <value>
                     <xsl:value-of select="."/>
                  </value>
               </xsl:for-each>
            </ValueList>
         </MultiValueParamResponse>
      </MultiValueParamResponses>
   </xsl:template>
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

これは私が得るものです:

<?xml version="1.0" encoding="UTF-16"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap-env:Header/>
    <soap-env:Body>
        <testService facade="FacadeReplaced" xmlns="http://new.webservice.namespace">
            <input>
                <Data1>Data 1</Data1>
                <Data2>Data 2</Data2>
                <ParamResponses>
                    <ParamResponse>
                        <Name>DATAONE</Name>
                        <ValParam>Text 1</ValParam>
                    </ParamResponse>
                    <ParamResponse>
                        <Name>DATATWO</Name>
                        <ValParam>Text 2</ValParam>
                    </ParamResponse>
                    <ParamResponse>
                        <Name>MULTIVALUED</Name>
                        <ValParam>001</ValParam>
                        <ValParam>002</ValParam>
                    </ParamResponse>
                    <ParamResponse>
                        <Name>DATATHREE</Name>
                        <ValParam>Text 3</ValParam>
                    </ParamResponse>
                </ParamResponses>
            </input>
        </testService>
    </soap-env:Body>
</soap-env:Envelope>

しかし、これは私が取得したいものです:

<?xml version="1.0" encoding="UTF-16"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap-env:Header/>
    <soap-env:Body>
        <testService facade="FacadeReplaced" xmlns="http://new.webservice.namespace">
            <input>
                <Data1>Data 1</Data1>
                <Data2>Data 2</Data2>
                <ParamResponses>
                    <ParamResponse>
                        <ParamResponse>
                            <Name>DATAONE</Name>
                            <ValParam>Text 1</ValParam>
                        </ParamResponse>
                    </ParamResponse>
                    <ParamResponse>
                        <ParamResponse>
                            <Name>DATATWO</Name>
                            <ValParam>Text 2</ValParam>
                        </ParamResponse>
                    </ParamResponse>
                    <ParamResponse>
                        <ParamResponse>
                            <Name>DATATHREE</Name>
                            <ValParam>Text 3</ValParam>
                        </ParamResponse>
                    </ParamResponse>
                </ParamResponses>
                <MultiValueParamResponses>
                    <MultiValueParamResponse>
                        <Name>MULTIVALUED</Name>
                        <ValueList>
                            <value>001</value>
                            <value>002</value>
                        </ValueList>
                    </MultiValueParamResponse>
                </MultiValueParamResponses>
            </input>
        </testService>
    </soap-env:Body>
</soap-env:Envelope>

要素入力に xmlns を追加すると、それは正しく取得されますが、それは Web サービスによって受け取るものではありません。

変換は XSLT 1.0 である必要があります。

4

2 に答える 2

2

問題は確かに名前空間に関連しています。元の XML には、次の行があります。

 <testService facade="Test" xmlns="http://new.webservice.namespace">

これはtestService要素を意味し、その下のすべての要素は " http://new.webservice.namespace " の一部になります (他の名前空間宣言によってオーバーライドされない限り)。

ただし、XSLT では、この名前空間について言及されていません。これは、このような表現がある場合を意味します...

<xsl:template match="input/ParamResponses">

NO 名前空間に属する要素を探しています。ソース XML には名前空間内に要素があるため、このテンプレートは何にも一致しません。あなたの場合、ID テンプレートが代わりに一致し、出力が入力と同じになります。

したがって、XSLT で名前空間を宣言する必要があります。

<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ns="http://new.webservice.namespace">

次に、入力 XML から要素を参照するたびに、関連する名前空間プレフィックスを使用する必要があります。

<xsl:template match="ns:input/ns:ParamResponses">

名前空間プレフィックス「ns」は、実際には何でもかまいません。XML の URI と一致する必要があるのは、URI " http://new.webservice.namespace " です。

さらに、出力する新しい要素について、これらを名前空間の一部にしたい場合は、それらに名前空間のプレフィックスを付けるか、出力する新しい要素に適用されるデフォルトの名前空間を XSLT で宣言することができます。プレフィックスを持たない

このXSLTを試してください

<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ns="http://new.webservice.namespace"
     xmlns="http://new.webservice.namespace">

   <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@facade">
        <xsl:attribute name="facade">
               <xsl:text>FacadeReplaced</xsl:text>
            </xsl:attribute>
    </xsl:template>
   <xsl:template match="ns:input/ns:ParamResponses">
      <ParamResponses>
         <xsl:for-each select="ns:ParamResponse[ns:Name!='MULTIVALUED']">
            <ParamResponse>
               <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
            </ParamResponse>
         </xsl:for-each>
      </ParamResponses>
      <MultiValueParamResponses>
         <MultiValueParamResponse>
            <Name>MULTIVALUED</Name>
           <xsl:variable name="items" select="//ns:input/ns:ParamResponses/ns:ParamResponse[ns:Name='MULTIVALUED']/ns:ValParam"/>
            <ValueList>
               <xsl:for-each select="$items">
                  <value>
                     <xsl:value-of select="."/>
                  </value>
               </xsl:for-each>
            </ValueList>
         </MultiValueParamResponse>
      </MultiValueParamResponses>
   </xsl:template>
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>
于 2013-10-18T12:03:17.220 に答える