1

我正在尝试建立一个肥皂请求。所需的输出是:

<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=""。你能给我指出正确的方向来消除这些不需要的伪影吗?

谢谢。

4

2 回答 2

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">
于 2013-04-07T14:09:51.933 回答
-1

I strongly recommend to separate the presentation from the logic. In fact, you can have a transformation that is independent of any possible presentation.

Here comes the "Fill-in-the-blanks" technique (note that it also solves your problem of unwanted namespaces):

Source XML document:

<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>

Presentation-independent transformation:

<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>

Result:

<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>

You can have now as many different presentation layouts as necessary, and the same transformation without any change (provided all required parameters have been specified) produces any of these formats.

For example, if you want to produce the result in this new format:

<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>

just apply the same transformation on the following XML document:

<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>

Further generalization can be achieved by providing the URL of the layout-document and the url of the Parameters document -- as parameters to the transformation.

于 2013-04-07T16:05:13.073 回答