XSLT conversion that removes all namespaces from soap: env

I have this input XML to which I have to apply XSL and convert it to another XML, which is on a higher version. Suppose V3. Thus, the input XML file is on version 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 which I apply

  <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> 

and the conclusion that I get is

 <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> 

It removes all namespace declarations from 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"

and the conclusion I want

 <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> 

I would appreciate it if someone could tell me what is missing in my XSL.

+4
source share
3 answers

The following XSLT saves all namespace declarations (used and unused) and changes tns to 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> 

It outputs the following result with Saxon 9.x (does not save unused namespaces with Xalan, but it seems to be related to 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> 
+2
source

Not sure why you are saying that it removes all these namespace prefix declarations. It breaks down those that are not needed, but leaves ads for NS2 and soapenv (and soapenv ).

When declaring unused namespace prefixes, nothing is done. What do you care? All elements in your output XML are in the correct namespace. This is important for any downstream XML consumer.

(I assume that changing the namespace URI for NS2 not part of the problem you are trying to solve.)

XSLT ensures that every element in the output XML is in the correct namespace. In addition, it does not provide precise control over where namespace prefixes are declared, since this does not affect the semantics of the output XML.

+2
source

The difference between xsl:element name="{name()}" and xsl:copy is that xsl:copy copies the namespace declarations, but xsl:element does not. So use xsl:copy if you want to keep them.

+2
source

Source: https://habr.com/ru/post/1486333/


All Articles