0

我有一个相对简单的 Soap 响应消息 XML,我想用 XSLT 对其进行修改。

这是我到目前为止所拥有的:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
    xmlns:z="http://some.url/WS/">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:variable name="Method" select="name(//soap:Body/*)" />

    <xsl:template match="//soap:Body/*" >
      <xsl:choose>
        <xsl:when test="$Method='Method1Response'">
          <xsl:call-template name="Method1" />
        </xsl:when>
        <xsl:otherwise>

        </xsl:otherwise>
      </xsl:choose>      
    </xsl:template>

      <xsl:template name="Method1" match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" />

</xsl:stylesheet>

示例 XML:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
  <wsa:Action></wsa:Action>
  <wsa:MessageID></wsa:MessageID>
  <wsa:RelatesTo></wsa:RelatesTo>
  <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
</env:Header>
  <soap:Body>
    <Method1Response xmlns="http://some.url/WS/">
      <Method1Result>
        <Msg>blah blah</Msg>
        <Errors>
          <ErrorItem>error 1</ErrorItem>
          <ErrorItem>error 2</ErrorItem>
        </Errors>
        <Data />
      </Method1Result>
    </Method1Response>
  </soap:Body>
</soap:Envelope>

这个想法是从 Method1Result 下删除错误,如果 Method1 = 特定值。如果没有,请保持原样。我目前拥有的,它没有做。谢谢。

进一步澄清的另一个编辑:我希望为属于不同 Web 服务调用的多个 XML 文件创建一个 XSLT 文件。这意味着 Method1 可以有许多不同的值,例如:GetMeal、GetWindow、GetHandle、GetWeatherReport……我希望为同一个 XSLT 中的每个值创建一个“案例”,以便故意“破坏”用于测试目的的预期 XML。每次我都会删除一个不同的元素。

4

2 回答 2

0

问题是匹配的模板//soap:Body/*调用了一个命名模板,它本身不输出任何东西。这导致soap:Body下的所有元素都被忽略。

由于您已经有一个模板来匹配您要删除的元素,您可以删除与soap:Body匹配的模板,您应该会发现它会按预期工作。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:z="http://some.url/WS/"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" /> 
</xsl:stylesheet> 

当这应用于您的示例 XML 时,将输出以下内容

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
   <env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
      <wsa:Action/>
      <wsa:MessageID/>
      <wsa:RelatesTo/>
      <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
   </env:Header>
   <soap:Body>
      <Method1Response xmlns="http://some.url/WS/">
         <Method1Result>
            <Msg>blah blah</Msg>
            <Data/>
         </Method1Result>
      </Method1Response>
   </soap:Body>
</soap:Envelope>

编辑:没有理由你不能有更多匹配的模板来处理你可能会得到的其他方法响应。例如....

<xsl:template match="//soap:Body/z:GetMealResponse/z:GetMealResult/z:Leftovers" />
<xsl:template match="//soap:Body/z:Method1Response/z:Method1Result/z:Errors" /> 
于 2012-05-16T12:14:57.500 回答
0

从您的样式表示例中:

<xsl:variable name="Method" select="name(//soap:Body/*)" />

<xsl:template match="//soap:Body/*" >
  <xsl:choose>
    <xsl:when test="$Method='Method1Response'">
      <xsl:call-template name="Method1" />

摆脱变量$Method,你不需要它。

注意匹配模式(如match="//soap:Body/*",这很尴尬),与 *search 表达式(如select="name(//soap:Body/*)")相比,通常相当简单,不需要 search-the-whole-doc 运算符(因此您可以简化为match="soap:Body/*")。

无需使用显式条件逻辑,只需提供一个与您的特殊情况匹配的模板,并确保它具有比其他候选模板更高的优先级,以便匹配:

<xsl:template match="z:Method1Response"/><!-- suppressed -->

或明确提高优先级:

<xsl:template match="z:Method1Response" priority="2"/>

或更具体地说,对于包含的错误:

<xsl:template match="z:Method1Response[z:Method1Result/z:Errors]"/>
于 2012-05-16T12:26:23.437 回答