我有这个输入XML,我需要将XSL应用到XSL并将其转换为更高版本的另一个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中缺少什么,我将不胜感激。
答案 0 :(得分:2)
不确定为什么你说它剥离了所有这些名称空间前缀声明。它剥离了那些不需要的东西,但它留下了NS2
和tns
(以及soapenv
)的声明。
对未使用的名称空间前缀进行声明不会产生任何结果。你为什么在乎?输出XML中的所有元素都在正确的命名空间中。这对任何下游XML消费者都很重要。
(我假设NS2
的名称空间URI的更改不是您尝试解决的问题的一部分。)
XSLT确保输出XML中的每个元素都在适当的命名空间中。除此之外,它不能很好地控制声明名称空间前缀的位置,因为它不会影响输出XML的语义。
答案 1 :(得分:2)
xsl:element name="{name()}"
和xsl:copy
之间的区别在于xsl:copy
复制了命名空间声明,而xsl:element
则没有。如果您希望保留它们,请使用xsl:copy
。
答案 2 :(得分:2)
以下XSLT保留所有名称空间声明(已使用和未使用),并将tns
namespace-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>