动态XSLT转换

use*_*829 5 xslt

我在下面有一个传入的简单xml请求,需要将其转换为具有正确名称空间的SOAP消息。在传入的XML请求中,名称空间不会出现,因此在形成SOAP消息时,我们还需要注意名称空间。是否有任何XSLT代码段可以帮助我实现这一目标。注意-我们需要动态地执行此XSLT转换,就像传入请求可以是任何元素(如“ GetImageRequest”)一样,因此基于此元素需要构造名称空间。(可能我们可以将所有名称空间保留在一个xml文件中,并且需要构造SOAP消息)

传入的XML请求:

<request>
<payload>
<GetImageRequest>
   <participantId>1191152220010</participantId>
   <participantCode>131029</participantCode>
   <groupCode>027198</groupCode>
   <userType>EE</userType>
   <clientName>Test</clientName>
   <shoeboxID>123444</shoeboxID>
   <imageID>45235</imageID>
</GetImageRequest>
</payload>
</request>
Run Code Online (Sandbox Code Playgroud)

==================需要在SOAP消息下面使用适当的名称空间进行构造。

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>

   </soapenv:Header>
   <soapenv:Body>
      <get:GetShoeboxItemRequest xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
         <get:participantId>1060687620010</get:participantId>
         <get:participantCode>1060687620010</get:participantCode>
         <get:groupCode>027198</get:groupCode>
         <get:userType>EE</get:userType>
         <get:clientName>Test</get:clientName>
         <get:shoeboxID>123444</get:shoeboxID>
      </get:GetShoeboxItemRequest>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

在这方面需要快速帮助。XSLT代码段将很有帮助。

Dim*_*hev 4

这种转变

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pRequestedItemName" select="'Shoebox'"/>

 <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
 <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vLcItemName" select=
                "translate($pRequestedItemName, $vUpper, $vLower)"/>

 <xsl:variable name="vDynNamespace" select=
   "concat('urn:webservice/server/mobile/', $vLcItemName, '/types/v1/Get', 'Item')"/>

  <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
            </soapenv:Header>
            <soapenv:Body>
              <xsl:element name="get:Get{$pRequestedItemName}ItemRequest" 
                   namespace="{$vDynNamespace}">
                <xsl:apply-templates select="/*/*/GetImageRequest/node()"/>
              </xsl:element>
            </soapenv:Body>
        </soapenv:Envelope>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="get:{name()}" namespace="{$vDynNamespace}">
      <xsl:copy-of select="namespace::*|@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于提供的源 XML 文档时

<request>
    <payload>
        <GetImageRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </GetImageRequest>
    </payload>
</request>
Run Code Online (Sandbox Code Playgroud)

产生想要的正确结果

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <get:GetShoeboxItemRequest
         xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetItem">
         <get:participantId>1191152220010</get:participantId>
         <get:participantCode>131029</get:participantCode>
         <get:groupCode>027198</get:groupCode>
         <get:userType>EE</get:userType>
         <get:clientName>Test</get:clientName>
         <get:shoeboxID>123444</get:shoeboxID>
         <get:imageID>45235</get:imageID>
      </get:GetShoeboxItemRequest>
   </soapenv:Body>
</soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)

解释

  1. <xsl:element>使用指令的全部力量。
  2. AVT属性值模板)的使用
  3. 动态命名空间的唯一变量部分应由转换的调用者提供为全局参数。

如果您需要构造一个完全动态的命名空间(例如由转换的调用者传入全局参数),请参阅此答案


更新

OP 在评论中澄清说,他可以将所有特定于请求的命名空间收集在单独的 XML 文档或全局参数中。

这是这个已澄清问题的解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pRequestData">
   <r name="GetImageRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem"/>
   <r name="SaveShoeBoxitemRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem"/>
   <r name="SaveClaimWithReceiptRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/SaveClaimAndReceipt"/>
   <r name="GetThumbNailImageRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnail"/>
   <r name="AttachReceiptwithExistingClaimRequest" 
    ns="urn:webservice/server/mobile/shoebox/types/v1/AttachClaimAndReceipt"/>
 </xsl:param>

 <xsl:variable name="vParams" select="document('')/*/xsl:param[@name='pRequestData']"/>

  <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
            </soapenv:Header>
            <soapenv:Body>
                <xsl:apply-templates select="/*/*/*"/>
            </soapenv:Body>
        </soapenv:Envelope>
  </xsl:template>

  <xsl:template match="*">
    <xsl:param name="pKey" select="local-name()"/>
    <xsl:element name="get:{local-name()}" namespace="{$vParams/*[@name = $pKey]/@ns}">
      <xsl:copy-of select="namespace::*|@*"/>
      <xsl:apply-templates>
        <xsl:with-param name="pKey" select="$pKey"/>
      </xsl:apply-templates>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当此转换应用于以下 XML 文档(所提供的文档具有第二个不同名称的子文档payload)时:

<request>
    <payload>
        <GetImageRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </GetImageRequest>
        <SaveShoeBoxitemRequest>
            <participantId>1191152220010</participantId>
            <participantCode>131029</participantCode>
            <groupCode>027198</groupCode>
            <userType>EE</userType>
            <clientName>Test</clientName>
            <shoeboxID>123444</shoeboxID>
            <imageID>45235</imageID>
        </SaveShoeBoxitemRequest>
    </payload>
</request>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果(与其他答案中的“解决方案”不同)

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
       <soapenv:Header/>
       <soapenv:Body>
          <get:GetImageRequest 
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/GetShoeboxItem">
             <get:participantId>1191152220010</get:participantId>
             <get:participantCode>131029</get:participantCode>
             <get:groupCode>027198</get:groupCode>
             <get:userType>EE</get:userType>
             <get:clientName>Test</get:clientName>
             <get:shoeboxID>123444</get:shoeboxID>
             <get:imageID>45235</get:imageID>
          </get:GetImageRequest>
          <get:SaveShoeBoxitemRequest 
xmlns:get="urn:webservice/server/mobile/shoebox/types/v1/SaveShoeboxItem">
             <get:participantId>1191152220010</get:participantId>
             <get:participantCode>131029</get:participantCode>
             <get:groupCode>027198</get:groupCode>
             <get:userType>EE</get:userType>
             <get:clientName>Test</get:clientName>
             <get:shoeboxID>123444</get:shoeboxID>
             <get:imageID>45235</get:imageID>
          </get:SaveShoeBoxitemRequest>
       </soapenv:Body>
    </soapenv:Envelope>
Run Code Online (Sandbox Code Playgroud)