为什么这个XSLT提取soap:Body也有soap:Header元素值

时间:2013-03-28 16:57:38

标签: xml xslt soap

我有来自客户的以下肥皂信封

<soap:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Header>
  <wsa:Action>http://company.com/services/InterfacePoint/CallResponse</wsa:Action>
  <wsa:MessageID>uuid:85fafb9d-9ec0-4017-a367-4f9043812310</wsa:MessageID>
  <wsa:To>http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:To>
  <wsse:Security>
     <wsu:Timestamp wsu:Id="Timestamp-dc059677-19f6-4b2c-a69b-ec0dffc6b1db">
        <wsu:Created>2013-03-28T16:24:33Z</wsu:Created>
        <wsu:Expires>2013-03-28T16:29:33Z</wsu:Expires>
     </wsu:Timestamp>
  </wsse:Security>
</soap:Header>
<soap:Body>
  <TXLife xsi:schemaLocation="http://ACORD.org/Standards/Life/2 TXLife2.22.00.XSD" xmlns="http://ACORD.org/Standards/Life/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  .
  .
  . 
  </TXLife>
 </soap:Body> 
</soap:Envelope>

我只想检索soap:Body内的内容并放弃其他所有内容。我写了这个XSLT来提取

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:template match="soap:Envelope/soap:Body">
      <xsl:copy-of select="@*|node()" />    
  </xsl:template> 
</xsl:stylesheet>

当肥皂信封中没有标题但是如果我将其应用于上面的XSLT时,此XML正常工作,它也会输出标题元素的值,因此它产生的输出是:

http://company.com/services/InterfacePoint/CallResponseuuid:85fafb9d-9ec0-4017-a367-4f9043812310http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous2013-03-28T16:24:33Z2013-03-28T16:29:33Z<TXLife xmlns="http://ACORD.org/Standards/Life/2"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
        xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
        xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
        xsi:schemaLocation="http://ACORD.org/Standards/Life/2 TXLife2.22.00.XSD">
.
.
.
</TXLife>

但我希望输出为:

<TXLife xmlns="http://ACORD.org/Standards/Life/2">
.
.
.
</TXLife>

我不在乎是否存在其他名称空间。

1 个答案:

答案 0 :(得分:3)

这是因为文本节点有一个默认模板,可以将其内容复制到输出中。为了使您的方法有效,您需要通过添加

来抑制它
<xsl:template match="text()" />

现在,如果你的soap:Body只有一个子元素,你应该得到格式正确的结果,但它仍然会包含额外的命名空间声明。

我会从不同的角度使用身份模板而不是副本来解决问题。 XSLT 2.0具有方便的copy-namespaces="no",您可以在<xsl:copy>上使用它来删除不必要的命名空间声明:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- extract just the first child of the body -->
  <xsl:template match="/">
    <xsl:apply-templates select="/soap:Envelope/soap:Body/*[1]" />
  </xsl:template>

  <!-- identity template, but dropping namespace declarations not used
       directly by this element -->
  <xsl:template match="@*|node()">
    <xsl:copy copy-namespaces="no">
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <!-- drop xsi:schemaLocation attributes -->
  <xsl:template match="@xsi:schemaLocation" />
</xsl:stylesheet>