将新的名称空间前缀添加到SOAP请求的主体中,该请求在原始XML中不存在或引用

时间:2013-11-14 18:38:54

标签: web-services xslt soap

我有一个由表单填充的XML值列表。基于特定元素的值,在本例中 Type ,我需要动态构造SOAP请求。只使用源XML中的某些元素,具体取决于类型。另外,我需要为SOAP主体中的每个元素添加一个名称空间前缀,该元素在源XML中不以任何方式存在或引用。

以下列格式给出XML输入:

<User>
    <Action>Update</Action>
    <Id>123-45-5678</Id>
    <Type>Student</Type>
    <Validate>true</Validate>
    <Grade>11</Grade>
    <Classroom/>
    <UserName/>
    <Password/>
</User>

如果我应用以下转换:

<xsl:stylesheet version="1.0" xmlns:ztx="http://tempuri.org/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:variable name="Action" select="/User/Action"/>
    <xsl:variable name="Id"     select="/User/Id"/>
    <xsl:variable name="Type"   select="/User/Type"/>
    <xsl:variable name="Method" select="concat('ztx:', $Action, $Type)"/>

    <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header/>
            <soapenv:Body>
                <xsl:element name="{$Method}">
                    <xsl:if test="$Action != 'Create'">
                        <xsl:copy-of select="/User/Id"/>
                    </xsl:if>
                    <xsl:if test="$Action != 'Delete'">
                        <xsl:choose>
                            <xsl:when test="$Type = 'Teacher'">
                                <xsl:copy-of select="/User/Classroom"/>
                            </xsl:when>
                            <xsl:when test="$Type = 'Student'">
                                <xsl:copy-of select="/User/Grade"/>
                            </xsl:when>
                            <xsl:when test="$Type = 'Administrator'">
                                <xsl:copy-of select="/User/UserName"/>
                                <xsl:copy-of select="/User/Password"/>
                            </xsl:when>
                        </xsl:choose>
                        <xsl:copy-of select="/User/Validate"/>
                    </xsl:if>
                </xsl:element>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>

</xsl:stylesheet>

我得到以下输出:

<soapenv:Envelope  xmlns:ztx="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
        <ztx:UpdateStudent>
            <Id>123-45-5678</Id>
            <Grade>11</Grade>
            <Validate>true</Validate>
        </ztx:UpdateStudent>
    </soapenv:Body>
</soapenv:Envelope>

然而,我想要的输出是:

<soapenv:Envelope  xmlns:ztx="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header/>
    <soapenv:Body>
        <ztx:UpdateStudent>
            <ztx:Id>123-45-5678</ztx:Id>
            <ztx:Grade>11</ztx:Grade>
            <ztx:Validate>true</ztx:Validate>
        </ztx:UpdateStudent>
    </soapenv:Body>
</soapenv:Envelope>

如果可能的话,我想优雅地完成这项工作,并且只需一次转换。寻找一种通用方法,可能使用另一个模板,只处理SOAP主体中的每个元素并添加命名空间,而不是单独对它们进行硬编码。

注意:我受限于XSLT 1.0

谢谢!

1 个答案:

答案 0 :(得分:1)

就像您在问题中提到的那样,您可以添加另一个模板,将名称空间前缀添加到SOAP响应的元素中。

这是模板

<xsl:template name="addNamespace" match="User/*">
  <xsl:element name="{concat('ztx:',name(.))}">
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

然后您只需将所有copy-of更改为apply-templates,然后再使用新模板。