使用XSLT排除XML空元素

时间:2017-05-02 16:12:20

标签: xml xslt

我有以下xml输入文件,并尝试获取没有空节点的输出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>
</soap:Envelope>

我希望输出类似于以下xml:

<?xml version="1.0" encoding="UTF-8"?>
   <Verification_response>
     <System_Data>
          <STATUSMESSAGE>0</STATUSMESSAGE>
          <TRANSACTIONID>41904</TRANSACTIONID>
     </System_Data>
   </Verification_response>

1 个答案:

答案 0 :(得分:0)

你的样式表有几个问题可以解释为什么你发现这很困难。

首先,它完全是单片式的:您只有一个与根节点匹配的模板规则,这使得添加条件逻辑非常混乱。你应该瞄准&#34;递归下降&#34;模式,其中每个节点都使用与节点匹配的模板规则进行处理,并调用apply-templates来处理其子节点。

其次,使用disable-output-escaping只是奇怪的。我很惊讶我经常在初学者身上看到这一点&#39;样式表。在某些情况下,它已经完成了,因为人们还没有理解XSLT是关于生成节点树的结果,它不是关于生成词汇XML。但在这种情况下,它只是不必要和错误:如果你的文本中有特殊字符,那么你希望它们被转义,并且当特殊字符出现在数据中时,禁用转义只会给你输出错误。不要这样做。

现在问你的问题。

首先添加

是一个好主意
<xsl:strip-space elements="*"/>

对于这种XML,其中空格没有意义,只是妨碍了。

现在您可以为Status和TransId元素编写规则:

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

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

其他元素的一般规则似乎是:

<xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

虽然这实际上是默认规则,但如果您愿意,可以将其删除。

现在你说你想要一个你不想要空节点的规则。我解释这个问题有点困难,因为你没有给出足够的例子。但是,如果TransId为空,请假设您不想输出TRANSACTIONID元素。然后,您可以通过为空元素添加更高优先级的规则来实现此目的:

<xsl:template match="*[not(child::node)]"/>

然后你的顶级规则应该是:

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