使用XSLT从XML中过滤空元素

时间:2017-12-19 16:07:49

标签: xml xslt

输入xml具有以下结构:

 <EagleML>  
    <referenceTransaction>
        <rating>
            <effectiveDate>2012-12-14</effectiveDate>
            <ratingDataModel>
                <ratingChar1>TH_45</ratingChar1>
            </ratingDataModel>
        </rating>
    </referenceTransaction>
    <referenceTransaction>
        <rating>
            <effectiveDate>2012-12-14</effectiveDate>
            <ratingDataModel>
                <ratingChar1>WL_CONCERN</ratingChar1>
            </ratingDataModel>
        </rating>
    </referenceTransaction>
    <referenceTransaction>
        <rating>
            <effectiveDate></effectiveDate>
            <ratingDataModel>
                <ratingChar1>WL_CONCERN</ratingChar1>
            </ratingDataModel>
        </rating>
    </referenceTransaction>
</EagleML>

在输出中,我需要使用XSLT来获取由元素referenceTransaction过滤的XML。 保留那些referenceTransaction节点, 其中包含非空的effectiveDate节点,而ratingChar1节点的值在WL上开始。 示例输出:

<EagleML>
    <referenceTransaction>
        <rating>
            <effectiveDate>2012-12-14</effectiveDate>
            <ratingDataModel>
                <ratingChar1>WL_CONCERN</ratingChar1>
            </ratingDataModel>
        </rating>
    </referenceTransaction>
</EagleML>

1 个答案:

答案 0 :(得分:1)

必需的表达

  

元素referenceTransaction。保留那些包含非空的effectiveDate节点的referenceTransaction节点,以及在WL上开始的ratingChar1节点的值。

可以在XPath中表示为

normalize-space(rating/effectiveDate) != '' and starts-with(rating/ratingDataModel/ratingChar1,'WL')

使用DeMorgan's laws这可以转换为

normalize-space(rating/effectiveDate) = '' or not(starts-with(rating/ratingDataModel/ratingChar1,'WL'))

匹配您要删除的所有referenceTransaction元素。然后,该表达式可用于空模板的谓词。

总体而言,身份模板复制所有节点,空模板更具体地匹配您要删除的元素。

整个样式表可能如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

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

<!-- empty template with predicate -->
<xsl:template match="referenceTransaction[normalize-space(rating/effectiveDate) = '' or not(starts-with(rating/ratingDataModel/ratingChar1,'WL'))]">
</xsl:template>

</xsl:stylesheet>