XSLT 删除重复的子节点

问题描述 投票:0回答:1

我有一个源输入 XML,我需要根据两个子节点删除重复记录。我是 XSLT 的新手,一直在 XSLT 1.0 和 2.0 中尝试各种方法来完成此任务,但没有成功。

源 XML:

<?xml version="1.0" encoding="UTF-8"?>
<DataSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <EDI.Table name="EDI.Table">
        <Row>
            <GroupId>A</GroupId>
            <MemberAltId>ABC123</MemberAltId>
            <PatientSeqId>002</PatientSeqId>
            <TotalMemberDeductible>499.52</TotalMemberDeductible>
        </Row>
        <Row>
            <GroupId>A</GroupId>
            <MemberAltId>ABC123</MemberAltId>
            <PatientSeqId>002</PatientSeqId>
            <TotalMemberOop>499.52</TotalMemberOop>
        </Row>
        <Row>
            <GroupId>A</GroupId>
            <MemberAltId>DEF123</MemberAltId>
            <PatientSeqId>001</PatientSeqId>
            <TotalMemberOop>50.00</TotalMemberOop>
        </Row>
    </EDI.Table>
</DataSet>

我已经查看了其他涉及删除重复项的 XSLT 示例,但我似乎无法让我的代码正常工作。我已使用以下 XSLT 来删除重复节点,但它根本不会更改源 XML。

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:key name="kMemberId" match="//Row" use="concat(MemberAltId,'|',PatientSeqId)"/>

<xsl:template match="/EDI.Table">
    <root>
        <xsl:for-each select="//Row[generate-id() = generate-id(key('kMemberId',concat(MemberAltId,'|',PatientSeqId))[1])]">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:for-each>
    </root>
</xsl:template>

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

</xsl:stylesheet>

XSLT 2.0 代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

<xsl:template match="/EDI.Table">
    <xsl:copy>
        <xsl:copy-of select="@* | Row"/>
        <xsl:for-each-group select="Row" group-by="MemberAltId">
            <xsl:for-each-group select="current-group()" group-by="PatientSeqId">
               <xsl:copy-of select="current-group()[1]"/>
          </xsl:for-each-group>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

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

预期输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<DataSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <EDI.Table name="EDI.Table">
        <Row>
            <GroupId>A</GroupId>
            <MemberAltId>ABC123</MemberAltId>
            <PatientSeqId>002</PatientSeqId>
            <TotalMemberDeductible>499.52</TotalMemberDeductible>
            <TotalMemberOop>499.52</TotalMemberOop>
        </Row>
        <Row>
            <GroupId>A</GroupId>
            <MemberAltId>DEF123</MemberAltId>
            <PatientSeqId>001</PatientSeqId>
            <TotalMemberOop>50.00</TotalMemberOop>
        </Row>
    </EDI.Table>
</DataSet>

如果有人可以帮助我实现上述预期的 XML,我将不胜感激。

xslt xslt-1.0 xslt-2.0
1个回答
0
投票

在 XSLT 2.0 中您可以执行以下操作:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes" />

<xsl:template match="EDI.Table">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each-group select="Row" group-by="concat(MemberAltId, '|', PatientSeqId)">
            <xsl:copy-of select="current-group()[1]"/>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

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

</xsl:stylesheet>

您尝试的主要问题是:

<xsl:template match="/EDI.Table">

这会尝试匹配名为 EDI.Table

root
元素,但该元素不存在,并且:

<xsl:copy-of select="@* | Row"/>

这会在输出唯一元素之前复制 all

Row
元素。

© www.soinside.com 2019 - 2024. All rights reserved.