删除XSLT转换后的xml中的空元素

时间:2017-05-04 15:29:56

标签: xml xslt-1.0

这个问题实际上与另一个my question有关。我有一个示例xml,一个xslt样式表和一个转换后的XML输出文件。我想要做的第一件事是我不希望在输出文件中生成没有值的元素。第二个是我想从结果文件中的第一个标签中删除那些名称空间声明。结果xml文件应如下所示

<Verification_response>
   <System_Data>
      <STATUSMESSAGE>0</STATUSMESSAGE>
      <TRANSACTIONID>41904</TRANSACTIONID>
   </System_Data>
</Verification_response>

XML输入文件:

    <?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
    <soap:Body>
        <InstantIDResponseEx xmlns="http://webservices.seisint.com/WsIdentity">
            <response>
                <Header>
                    <Status>0</Status>
                    <TransId>41904</TransId>
                    <User></User>
                </Header>
            <Result>
                 <Data/>
            </Result>
        </response>
    </InstantIDResponseEx>
</soap:Body>

XSLT样式表:

     <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:Identity="http://webservices.seisint.com/WsIdentity" 
                xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" version="1.0">
<xsl:strip-space elements="*"/>


    <!-- ****** MAIN TEMPLATE ******* -->
    <xsl:template match="/">
       <Verification_response>   
              <xsl:apply-templates select="/soap:Envelope/soap:Body/Identity:InstantIDResponseEx/Identity:response"/>
       </Verification_response>
    </xsl:template>

    <xsl:template match = "Identity:response"> 
      <System_Data>
      <xsl:apply-templates select = "Identity:Header" /> 
      </System_Data>
      <Received>
      <xsl:apply-templates select = "Identity:Result" /> 
      </Received>
   </xsl:template>  

    <xsl:template match="Identity:Header">
      <STATUSMESSAGE>
        <xsl:apply-templates select="Identity:Status"/>
      </STATUSMESSAGE>
      <TRANSACTIONID>
        <xsl:apply-templates select="Identity:TransId"/>     
      </TRANSACTIONID>
      <Client>
        <xsl:apply-templates select="Identity:User"/>
      </Client>
    </xsl:template>

    <xsl:template match="Identity:Result">
      <Content>
        <xsl:apply-templates select="Identity:Data"/>
      </Content>
    </xsl:template>

    <xsl:template match="Identity:Status">
        <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="Identity:TransId">
       <xsl:value-of select="."/>
    </xsl:template>     

    <xsl:template match="Identity:User">
       <xsl:value-of select="."/>
    </xsl:template> 

    <xsl:template match="Identity:Data">
        <xsl:value-of select="."/>
    </xsl:template>

</xsl:stylesheet>

转换后的XML:

    <Verification_response xmlns:Identity="http://webservices.seisint.com/WsIdentity"
                       xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                       xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext">
   <System_Data>
      <STATUSMESSAGE>0</STATUSMESSAGE>
      <TRANSACTIONID>41904</TRANSACTIONID>
      <Client/>
   </System_Data>
   <Received>
      <Content/>
   </Received>
</Verification_response>

我尝试在论坛中的另一个帖子的根节点之前添加以下代码,但它无效。任何人都可以帮我解决这个问题吗?

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

 <xsl:template match=
  "*[not(node())]
  |
   *[not(node()[2])
   and
     node()/self::text()
   and
     not(normalize-space())
     ]
  "/>

1 个答案:

答案 0 :(得分:0)

要删除命名空间声明,请将以下属性添加到xsl:stylesheet元素:exclude-result-prefixes="Identity wsse soap"

要删除空元素,您需要修改样式表结构。这里的问题是你在创建文字结果元素包装器而不检查是否存在任何内容。所以你需要有条件地创建它们 - 例如,改变:

<Received>
    <xsl:apply-templates select = "Identity:Result" /> 
</Received>

为:

<xsl:if test="Identity:Result//text()">
    <Received>
        <xsl:apply-templates select = "Identity:Result" /> 
    </Received>
</xsl:if>

或将包装器的创建移动到匹配Identity:Result的模板,并有条件地将模板应用于:

<xsl:apply-templates select = "Identity:Result[.//text()]" />

请注意,这会将“empty”解释为没有后代文本节点。