2

我有将由表单填充的值的 XML 列表。基于特定元素的值,在本例中为Type,我需要动态构造一个 SOAP 请求。将仅使用 Source XML 中的某些元素,具体取决于Type。此外,我需要为 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

谢谢!

4

1 回答 1

1

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

这是模板

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

然后您只需将所有内容更改copy-ofapply-templatesthen 即可使用新模板。

于 2013-11-14T19:27:17.000 回答