使用XSLT从XML过滤空元素



该输入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。留下这些参考术节点,包含非空作用节点和ratingchar1节点的值始于WL。示例输出:

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

所需的表达式

元素Referencetransaction。留下那些参考文献节点,其中包含非空作用节点,并且在WL上启动了ChratingChar1节点的值。

可以在xpath中以

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

使用Demorgan的定律,这可以倒置为

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>