使用 xslt 根据条件从 xml 文件中删除重复记录

问题描述

如果输入 xml 中出现具有重复 Emplid 的记录,那么我想删除 状态 为“已撤消”的记录。如果具有相同 emplid 的记录出现两次,我只想保留状态为活动的记录。

输入xml

<Recordset>
<Record>
    <Emplid>10001</Emplid>
    <name>Bob Dylan</name>
    <country>USA</country>
    <company>Columbia</company>
    <status>active</status>
    <year>1985</year>
</Record>
<Record>
    <Emplid>10002</Emplid>
    <name>Bonnie Tyler</name>
    <country>UK</country>
    <company>CBS Records</company>
    <status>withdrawn</status>
    <year>1988</year>
</Record>
<Record>
    <Emplid>10001</Emplid>
    <name>Bob Dylan</name>
    <country>Uk</country>
    <company>CBS Records</company>
    <status>withdrwan</status>
    <year>1975</year>
</Record>
</Recordset>

预期的 xml

Recordset>
<Record>
    <Emplid>10001</Emplid>
    <name>Bob Dylan</name>
    <country>USA</country>
    <company>Columbia</company>
    <status>active</status>
    <year>1985</year>
</Record>
<Record>
    <Emplid>10002</Emplid>
    <name>Bonnie Tyler</name>
    <country>UK</country>
    <company>CBS Records</company>
    <status>withdrawn</status>
    <year>1988</year>
</Record>
</Recordset>

感谢有人能帮助我。

解决方法

您可以尝试以下 XSLT。

XSLT

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

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

    <xsl:template match="Record[status='withdrawn']">
        <xsl:variable name="Emplid" select="./Emplid"/>
        <xsl:choose>
            <xsl:when test="count(/Recordset/Record[Emplid=$Emplid]) &gt; 1">
            </xsl:when>
            <xsl:when test="count(/Recordset/Record[Emplid=$Emplid]) = 1">
                <xsl:copy-of select="."/>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
,

所以基本上你想复制所有活动记录,以及任何没有活动记录的撤回记录和相同的 Emplid?

没错

好吧,那为什么不这样做呢:

XSLT 1.0

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

<xsl:key name="act" match="Record[status='active']" use="Emplid" />

<xsl:template match="/Recordset">
    <xsl:copy>
        <xsl:copy-of select="Record[status='active']"/>
        <xsl:copy-of select="Record[status='withdrawn'][not(key('act',Emplid))]"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

如果你想保持原来的顺序,可以将两个xsl:copy-of指令合二为一:

        <xsl:copy-of select="Record[status='active'] | Record[status='withdrawn'][not(key('act',Emplid))]"/>

注意使用 key 来解决交叉引用。