使用 xslt 删除重复节点 XML - 多条记录(xslt 2 或 3)
removing duplicate nodes XML using xslt - multiple records (xslt 2 or 3)
我有一个 XML 包含数百条这种格式的记录(此处仅显示 2 条)
<assessment>
<subject>
<Name>470 470 015</Name>
<LAD>3.446887644423149</LAD>
<LAD>3.446887644423149</LAD>
<LM>4.049357373198344</LM>
<LM>4.049357373198344</LM>
<RCA>3.283339910532276</RCA>
<RCA>3.283339910532276</RCA>
</subject>
<subject>
<Name>230 230067</Name>
<LAD>2.392278459908628</LAD>
<LAD>2.392278459908628</LAD>
<LM>3.50258194988953</LM>
<LM>3.50258194988953</LM>
<RCA>3.274917502338067</RCA>
<RCA>3.274917502338067</RCA>
</subject>
</assessment>
我想删除重复的节点,使其看起来像这样
<assessment>
<subject>
<Name>470 470 015</Name>
<LAD>3.446887644423149</LAD>
<LM>4.049357373198344</LM>
<RCA>3.283339910532276</RCA>
</subject>
<subject>
<Name>230 230067</Name>
<LAD>2.392278459908628</LAD>
<LM>3.50258194988953</LM>
<RCA>3.274917502338067</RCA>
</subject>
</assessment>
根据之前对类似问题 () 的回答中提到的代码,我能够处理第一条记录,但无法处理文件中的所有记录。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by="name()">
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
尝试更改:
match="/*"
至:
match="subject"
马丁评论道:
The current answers and your attempt identity duplicates based on the element/node name. I wonder whether you can have several elements of the same name (e.g. LAD
) inside of a subject
element which can have a different value and what you would need to do in that case.
一种选择是通过指定 composite="yes"
并将 .
或 normalize-space()
添加到 group-by
来使用复合键。这将保留每个元素的一个实例 name/value 组合。
示例...
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" expand-text="yes">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="subject">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by="name(),normalize-space()" composite="yes">
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
你的方法是正确的,我会这样做:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="subject">
<xsl:copy>
<xsl:for-each-group select="*" group-by="name()">
<xsl:copy-of select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我有一个 XML 包含数百条这种格式的记录(此处仅显示 2 条)
<assessment>
<subject>
<Name>470 470 015</Name>
<LAD>3.446887644423149</LAD>
<LAD>3.446887644423149</LAD>
<LM>4.049357373198344</LM>
<LM>4.049357373198344</LM>
<RCA>3.283339910532276</RCA>
<RCA>3.283339910532276</RCA>
</subject>
<subject>
<Name>230 230067</Name>
<LAD>2.392278459908628</LAD>
<LAD>2.392278459908628</LAD>
<LM>3.50258194988953</LM>
<LM>3.50258194988953</LM>
<RCA>3.274917502338067</RCA>
<RCA>3.274917502338067</RCA>
</subject>
</assessment>
我想删除重复的节点,使其看起来像这样
<assessment>
<subject>
<Name>470 470 015</Name>
<LAD>3.446887644423149</LAD>
<LM>4.049357373198344</LM>
<RCA>3.283339910532276</RCA>
</subject>
<subject>
<Name>230 230067</Name>
<LAD>2.392278459908628</LAD>
<LM>3.50258194988953</LM>
<RCA>3.274917502338067</RCA>
</subject>
</assessment>
根据之前对类似问题 (
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by="name()">
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
尝试更改:
match="/*"
至:
match="subject"
马丁评论道:
The current answers and your attempt identity duplicates based on the element/node name. I wonder whether you can have several elements of the same name (e.g.
LAD
) inside of asubject
element which can have a different value and what you would need to do in that case.
一种选择是通过指定 composite="yes"
并将 .
或 normalize-space()
添加到 group-by
来使用复合键。这将保留每个元素的一个实例 name/value 组合。
示例...
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" expand-text="yes">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="subject">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" group-by="name(),normalize-space()" composite="yes">
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
你的方法是正确的,我会这样做:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="subject">
<xsl:copy>
<xsl:for-each-group select="*" group-by="name()">
<xsl:copy-of select="current-group()[1]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>