xml - 使用 XSLT 向 SOAP XML 消息添加多个命名空间

标签 xml xslt soap namespaces

我有一个 SOAP 请求,我正尝试使用 XSLT 对其进行转换。我想为请求中的每个元素添加命名空间限定符。我需要用户使用两个不同的命名空间。这是我试图转换的 XML:

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" >
   <soapenv:Header/>
   <soapenv:Body>
      <PingRq>
         <RqUID>1</RqUID>
         <RequestContext>
              <ClientUserID>1</ClientUserID>
              <ClientName>Big Company</ClientName>
              <ClientApplication>
                  <AppName>TestApp</AppName>
                  <AppVersion>1</AppVersion>
              </ClientApplication>
              <ClientLangPref>En-US</ClientLangPref>
              <ClientDt>Mar-29-2013</ClientDt>
         </RequestContext>
      </PingRq>
      </soapenv:Body>
    </soapenv:Envelope

这是我想将其转换为:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" >
      <soapenv:Header/>
      <soapenv:Body>
       <PingRq namespace="http://www.ns1.com">
         <RqUID namespace="http://www.ns2.com">1</RqUID>
         <RequestContext namespace="http://www.ns2.com">
              <ClientUserID namespace="http://www.ns2.com">1</ClientUserID>
              <ClientName namespace="http://www.ns2.com">Big Company</ClientName>
              <ClientApplication namespace="http://www.ns2.com">
                  <AppName namespace="http://www.ns2.com">TestApp</AppName>
                  <AppVersion namespace="http://www.ns2.com">1</AppVersion>
              </ClientApplication>
              <ClientLangPref namespace="http://www.ns2.com">En-US</ClientLangPref>
              <ClientDt namespace="http://www.ns2.com">Mar-29-2013</ClientDt>
         </RequestContext>
         </PingRq>
       </soapenv:Body>
    </soapenv:Envelope>

这是我的样式表
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
     xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">

      <xsl:template match="@*|node()">
         <xsl:copy>
       <xsl:apply-templates select = "@*|node()" />
         </xsl:copy>
     </xsl:template>                

     <xsl:template match="PingRq">
    <xsl:element name="{local-name()}" namespace="http://www.ns1.com">
        <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
     </xsl:template>
     <xsl:template match="PingRq/*">
    <xsl:element name="{local-name()}" namespace="http://www.ns2.com">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
     </xsl:template>        
    </xsl:stylesheet>

这是我得到的结果。
<?xml version="1.0" encoding="UTF-8"?>
     <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
       <soapenv:Header/>
       <soapenv:Body>
        <PingRq xmlns="http://www.ns1.com">
         <RqUID xmlns="http://www.ns2.com">1</RqUID>
         <RequestContext xmlns="http://www.ns2.com">
              <ClientUserID xmlns="">1</ClientUserID>
              <ClientName xmlns="">Big Company</ClientName>
              <ClientApplication xmlns="">
                  <AppName>TestApp</AppName>
                  <AppVersion>1</AppVersion>
              </ClientApplication>
              <ClientLangPref xmlns="">En-US</ClientLangPref>
              <ClientDt xmlns="">Mar-29-2013</ClientDt>
         </RequestContext>
        </PingRq>
       </soapenv:Body>
      </soapenv:Envelope>

我不明白为什么我在后代中得到空的命名空间属性。任何人有任何想法???

最佳答案

PingRq/* xpath 只匹配 PingRq 的直接子代元素。要将其所有后代元素放在某个命名空间中,您可以这样做:

<xsl:template match="PingRq//*">
  <xsl:element name="{local-name()}" namespace="http://www.ns2.com">
    <xsl:apply-templates select="@*|node()"/>
   </xsl:element>
</xsl:template>

请注意,结果并未显示所有后代的命名空间声明:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
  <soapenv:Header />
  <soapenv:Body>
    <PingRq xmlns="http://www.ns1.com">
      <RqUID xmlns="http://www.ns2.com">1</RqUID>
      <RequestContext xmlns="http://www.ns2.com">
        <ClientUserID>1</ClientUserID>
        <ClientName>Big Company</ClientName>
        <ClientApplication>
          <AppName>TestApp</AppName>
          <AppVersion>1</AppVersion>
        </ClientApplication>
        <ClientLangPref>En-US</ClientLangPref>
        <ClientDt>Mar-29-2013</ClientDt>
      </RequestContext>
    </PingRq>
  </soapenv:Body>
</soapenv:Envelope>

但这是意料之中的,因为 RequestContext 下的元素从他们的父级继承他们的命名空间。

关于xml - 使用 XSLT 向 SOAP XML 消息添加多个命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14699279/

相关文章:

c# - 将 XML 中的 HTML 实体转换为 C# 中的等效 Unicode

xml - 将 ColdFusion 结构转换为 XML

java - 如何使用 XSLT v1.0 插入文本而不是使用 XSLT v2.0 正则表达式?

c# - 在 XSLT 1.0 和分组方面需要帮助

xml - 使用 XPath 选择匹配兄弟的前一个兄弟?

java - Spring 启动 : Use specific alias form keystore to consume HTTPS SOAP webservice

c# - 即使调用了 beforesendrequest 方法,SOAP header 也强制使用 Mustunderstand = 1

soap - 在 switchyard 中从 WSDL 创建 Java 文件时出现 java.lang.reflect.InitationTargetException

c# - 从具有相同名称的多个元素和 xml 中另一个元素的属性值获取属性值

xml - xslt编程时 'or'和 '|'有什么区别?