如何从xslt中删除xml输出中不需要的空xmlns

时间:2013-04-07 14:02:21

标签: xslt namespaces

我正在尝试构建一个Soap请求。所需的输出是:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"   
xmlns:soap1="http://acme.com/ws/soapheaders">
<soap:Header>
    <soap1:locale>en</soap1:locale>
    <soap1:authentication>
        <soap1:username>john.doe</soap1:username>
        <soap1:password>psw</soap1:password>
    </soap1:authentication>
</soap:Header>

这是我的测试xsl(语言,用户名和密码将在实际应用程序中传递):

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="language" select="'en'"/>
<xsl:param name="username" select="'john.doe'"/>
<xsl:param name="password" select="'psw'"/>
<xsl:template match="/">
    <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
        xmlns:soap1="http://acme.com/ws/soapheaders" >
        <xsl:call-template name="soapHeader"/>              
        <xsl:call-template name="soapBody"/>
    </soap:Envelope>
</xsl:template>
<xsl:template name="soapHeader">
    <soap:Header> 
        <soap1:locale><xsl:value-of select="$language" /></soap1:locale>
        <soap1:authentication>
            <soap1:username><xsl:value-of select="$username" /></soap1:username>
            <soap1:password><xsl:value-of select="$password" /></soap1:password>
        </soap1:authentication>
    </soap:Header> 
</xsl:template>
<xsl:template name="soapBody">
</xsl:template>
</xsl:stylesheet>

然而,输出是:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="http://acme.com/ws/soapheaders">
<soap:Header xmlns:soap="">
    <soap1:locale xmlns:soap1="">en</soap1:locale>
    <soap1:authentication xmlns:soap1="">
        <soap1:username>john.doe</soap1:username>
        <soap1:password>psw</soap1:password>
    </soap1:authentication>
</soap:Header>

有不需要的空名称空间,例如xmlns:soap =“”,xmlns:soap1 =“”。你能指出我正确的方向消除这些不想要的文物吗?

感谢。

2 个答案:

答案 0 :(得分:1)

我很惊讶你的XSLT处理器接受XSLT,因为它不是有效的XML,但要使它有效并且(我相信)解决你的问题,你应该在<xsl:stylesheet>元素上声明命名空间在<soap:Envelope>元素上:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0"
                xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
                xmlns:soap1="http://acme.com/ws/soapheaders">

答案 1 :(得分:-1)

我强烈建议将演示文稿与逻辑分开。实际上,您可以进行独立于任何可能的演示的转换

这里出现了“填空”技术(请注意,它还可以解决您不需要的命名空间问题):

源XML文档

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:soap1="http://acme.com/ws/soapheaders" xmlns:gen="my:gen">
    <soap:Header>
        <soap1:locale><gen:language/></soap1:locale>
        <soap1:authentication>
            <soap1:username><gen:username/></soap1:username>
            <soap1:password><gen:password/></soap1:password>
        </soap1:authentication>
    </soap:Header>
</soap:Envelope>

与演示文稿无关的转换

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:gen="my:gen">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
    <xsl:param name="language" select="'en'"/>
    <xsl:param name="username" select="'john.doe'"/>
    <xsl:param name="password" select="'psw'"/>

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

 <xsl:template match="gen:*">
  <xsl:value-of select=
  "document('')/*/xsl:param[@name=local-name(current())]/@select"/>
 </xsl:template>
</xsl:stylesheet>

<强>结果

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="http://acme.com/ws/soapheaders" xmlns:gen="my:gen">
   <soap:Header>
      <soap1:locale>'en'</soap1:locale>
      <soap1:authentication>
         <soap1:username>'john.doe'</soap1:username>
         <soap1:password>'psw'</soap1:password>
      </soap1:authentication>
   </soap:Header>
</soap:Envelope>

您现在可以根据需要使用尽可能多的不同演示文稿布局,并且无需任何更改即可进行相同的转换(前提是已指定所有必需参数)会生成任何这些格式

例如,如果您想以这种新格式生成结果:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="http://acme.com/ws/soapheaders">
   <soap:Header>
      <soap1:personalized>
         <soap1:locale>
            <soap1:language>'en'</soap1:language>
         </soap1:locale>
         <soap1:authentication>
            <soap1:username>'john.doe'</soap1:username>
            <soap1:password>'psw'</soap1:password>
         </soap1:authentication>
      </soap1:personalized>
   </soap:Header>
</soap:Envelope>

只需对以下XML文档应用相同的转换:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:soap1="http://acme.com/ws/soapheaders" xmlns:gen="my:gen">
    <soap:Header>
      <soap1:personalized>
        <soap1:locale>
          <soap1:language><gen:language/></soap1:language>
    </soap1:locale>
        <soap1:authentication>
            <soap1:username><gen:username/></soap1:username>
            <soap1:password><gen:password/></soap1:password>
        </soap1:authentication>
        </soap1:personalized>
    </soap:Header>
</soap:Envelope>

通过提供layout-document的URL和Parameters文档的url作为转换的参数,可以实现进一步的泛化。