XSLT Transformation from SOAP

2019-09-02 18:09发布

I have a incoming SOAP message like below:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns3:GetImageResponse xmlns="urn:webservice/server/mobile/shoebox/types/v1/CustomImage" xmlns:ns2="urn:webservice/server/mobile/shoebox/types/v1/common/ShoeboxCommonArtifacts" xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" xmlns:ns4="urn:webservice/server/mobile/shoebox/types/v1/common/exceptions" xmlns:ns5="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnailImage">
<ns3:returnCode>105</ns3:returnCode>
<ns3:errorText>Invalid Participant code/id.</ns3:errorText>
<ns3:shoeboxImage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</ns3:GetImageResponse>
</soap:Body>
</soap:Envelope>


Need to transform into another simple XML like Below: (Constraint - The root element under BODY of SOAP envelope (ex- if "GetImageResponse" coming we need construct "GetImage" element in output XML) and it is not constant it can be any element So need to construct XML based on the root element under BODY , Ex shown below)

<?xml version="1.0" encoding="UTF-8"?>
<tns:GetImage xmlns:bons1="http://highmark.com/rbssvc/messages/common" xmlns:tns="http://www.example.org/GetImageResponseMessage/" xmlns:tns1="http://www.example.org/GetImageResponse/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/GetImageResponseMessage/ ../xsd/GetImageResponseMessage.xsd ">

 <payload>
    <returnCode>returnCode</returnCode>
    <errorText>errorText</errorText>
    <imageData>MA==</imageData>
  </payload>

I am using this below XSLT to transform:

<xsl:stylesheet extension-element-prefixes="dp" exclude-result-prefixes="dp regex" version="1.0" xmlns:dp="http://www.datapower.com/extensions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regex="http://exslt.org/regular-expressions">
   <xsl:template match="/">
      <GetImage>
         <xsl:element name="{'Payload'}">
            <xsl:copy-of select="/*/*[local-name()='Body']/*[local-name()='GetImageResponse']/*"/>
         </xsl:element>
      </GetImage>
   </xsl:template>
</xsl:stylesheet>

But i am not getting the desired XML output shown above

The out put which i am getting is :

<GetImageResponse>
   <Payload>
      <ns3:returnCode xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns5="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnailImage" xmlns:ns4="urn:webservice/server/mobile/shoebox/types/v1/common/exceptions" xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" xmlns:ns2="urn:webservice/server/mobile/shoebox/types/v1/common/ShoeboxCommonArtifacts" xmlns="urn:webservice/server/mobile/shoebox/types/v1/CustomImage">105</ns3:returnCode>
      <ns3:errorText xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns5="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnailImage" xmlns:ns4="urn:webservice/server/mobile/shoebox/types/v1/common/exceptions" xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" xmlns:ns2="urn:webservice/server/mobile/shoebox/types/v1/common/ShoeboxCommonArtifacts" xmlns="urn:webservice/server/mobile/shoebox/types/v1/CustomImage">Invalid Participant code/id.</ns3:errorText>
      <ns3:shoeboxImage xsi:nil="true" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns5="urn:webservice/server/mobile/shoebox/types/v1/GetThumbnailImage" xmlns:ns4="urn:webservice/server/mobile/shoebox/types/v1/common/exceptions" xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" xmlns:ns2="urn:webservice/server/mobile/shoebox/types/v1/common/ShoeboxCommonArtifacts" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:webservice/server/mobile/shoebox/types/v1/CustomImage"/>
   </Payload>
</GetImageResponse>

The issue is here like i am not able to copy the name space of incoming soap message Like element "GetImageResponse" and some extra namespace are also coming for element "payload" .enter code here

Any idea how i can transform from SOAP message to the desired XML output.

Quick reply appreciated.

Regards Rj

标签: xslt
2条回答
做自己的国王
2楼-- · 2019-09-02 18:44

Your question is not entirely clear. I think you want to do something like this:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" 
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="soap ns3 my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<my:ns-holder xmlns:bons1="http://highmark.com/rbssvc/messages/common" xmlns:tns1="http://www.example.org/GetImageResponse/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/GetImageResponseMessage/ ../xsd/GetImageResponseMessage.xsd "/>

<xsl:template match="/soap:Envelope/soap:Body/*">
    <xsl:element name="tns:{local-name()}" xmlns:tns="http://www.example.org/GetImageResponseMessage/">
        <xsl:copy-of select="document('')/xsl:stylesheet/my:ns-holder/namespace::*"/>
        <payload>
            <returnCode>
                <xsl:value-of select="ns3:returnCode" />
            </returnCode>
            <errorText>
                <xsl:value-of select="ns3:errorText" />
            </errorText>
            <imageData>MA==</imageData>
        </payload>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

What this does is:

  1. Create a root element whose local name is the same as the name of the child of soap:Body, assign it a tns: prefix and bind the prefix to the "http://www.example.org/GetImageResponseMessage/' namespace. Note that this assumes there will be only one such child.

  2. Add a bunch of namespaces to the above root element. Note that these namespaces are not actually used in the result - and as such are entirely redundant.

  3. Create the payload and its value nodes. Note that you cannot use xsl:copy here, because that would also copy the original node's namespace (ns3 in this example).

Applied to your input example, the result here will be:

<?xml version="1.0" encoding="UTF-8"?>
<tns:GetImageResponse xmlns:tns="http://www.example.org/GetImageResponseMessage/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns3="urn:webservice/server/mobile/shoebox/types/v1/Image" xmlns:my="http://www.example.com/my" xmlns:bons1="http://highmark.com/rbssvc/messages/common" xmlns:tns1="http://www.example.org/GetImageResponse/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <payload>
      <returnCode>105</returnCode>
      <errorText>Invalid Participant code/id.</errorText>
      <imageData>MA==</imageData>
   </payload>
</tns:GetImageResponse>

I did not understand:

  • How exactly should GetImageResponse be tranformed into GetImage;
  • Where is the imageData value ("MA==") supposed to come from.
查看更多
冷血范
3楼-- · 2019-09-02 18:54

Well the redundant xmlns declarations are visual noise, but functionally not a problem. However you can fix this by making sure you set the necessary xmlns declarations on the root element of the result that you generate. In your case this is: <GetImage>.

You'll note that in your stylesheet the GetImage element is in the default namespace of the document which contains the XSLT stylesheet, which is also not specified.

Example:

<!-- 
     namespace GetImage and 
     set up additional namespace mapping for ns5 prefix
     for any copied elements which may be injected 
 -->
<tns:GetImage xmlns:tns="tns-uri" xmlns:ns5="ns5-uri">
    <!-- more stuff here -->
</tns:GetImage>

Next up your <xsl:element name="{'Payload'}"> call also does not inject a namespace. You can either use the namespace attribute of xsl:element to associate the generated element with the desired namespace (URI), or you can use the syntax {prefix}:{local-name} in the name attribute and add the appropriate xmlns:prefix declarations.

Examples:

<xsl:element name="foo" namespace="bar"/>
<!-- needs xmlns:ns declaration -->
<xsl:element name="ns:foo"/>
<!--  substantially the same, using 'expressions' instead of 'literals' -->
<xsl:element name="{$nsPrefix}:{local-name()}">
查看更多
登录 后发表回答