仅获取不在XML中重复的​​元素

时间:2013-05-04 21:44:07

标签: xslt duplicates

我有一个场景,其中XML文档包含一些重复的节点。我想摆脱所有这样的节点。 请注意,这是 删除重复项 ”。我想完全删除那些多次出现的节点的所有条目。

实施例 我的XML

<ReadUserOBSResponse>
 <UserOBS>
  <OBSObjectId>1510</OBSObjectId>
  <UserObjectId>443</UserObjectId>
 </UserOBS>
 <UserOBS>
  <OBSObjectId>540</OBSObjectId>
  <UserObjectId>514</UserObjectId>
 </UserOBS>
 <UserOBS>
  <OBSObjectId>1521</OBSObjectId>
  <UserObjectId>514</UserObjectId>
 </UserOBS>
 <UserOBS>
  <OBSObjectId>547</OBSObjectId>
  <UserObjectId>544</UserObjectId>
 </UserOBS>
</ReadUserOBSResponse>

所需输出:我想用UserObjectId 514

删除这两个条目
<ReadUserOBSResponse>
 <UserOBS>
  <OBSObjectId>1510</OBSObjectId>
  <UserObjectId>443</UserObjectId>
 </UserOBS>
 <UserOBS>
  <OBSObjectId>547</OBSObjectId>
  <UserObjectId>544</UserObjectId>
 </UserOBS>
</ReadUserOBSResponse>

我做过一些事情,但它没有用。我的想法是用UserObjectId作为当前值来计算节点,将其放在xsl:if中,然后打印节点。 但我不确定如何编写这个片段。

3 个答案:

答案 0 :(得分:2)

这将满足您的需求。

它有一个UserOBS元素的模板,用于检查其父级中是否只有一个UserOBS子级具有UserObjectId的相同值。如果是这样,整个节点将被复制到输出。

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

    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/ReadUserOBSResponse">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="UserOBS">
        <xsl:if test="count(../UserOBS[UserObjectId = current()/UserObjectId]) = 1">
            <xsl:copy-of select="."/>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0" encoding="utf-8"?>
<ReadUserOBSResponse>
   <UserOBS>
      <OBSObjectId>1510</OBSObjectId>
      <UserObjectId>443</UserObjectId>
   </UserOBS>
   <UserOBS>
      <OBSObjectId>547</OBSObjectId>
      <UserObjectId>544</UserObjectId>
   </UserOBS>
</ReadUserOBSResponse>

答案 1 :(得分:2)

这是一种使用密钥的非常有效(简洁)的方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*" />
  <xsl:key name="kUOId" match="UserOBS" use="UserObjectId" />

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

  <xsl:template match="UserOBS[key('kUOId', UserObjectId)[2]]" />
</xsl:stylesheet>

在样本输入上运行时,结果为:

<ReadUserOBSResponse>
  <UserOBS>
    <OBSObjectId>1510</OBSObjectId>
    <UserObjectId>443</UserObjectId>
  </UserOBS>
  <UserOBS>
    <OBSObjectId>547</OBSObjectId>
    <UserObjectId>544</UserObjectId>
  </UserOBS>
</ReadUserOBSResponse>

答案 2 :(得分:1)

XSLT 2.0中更简单:

<xsl:for-each-group select="UserObs" group-by="UserObjectId">
  <xsl:copy-of select="current-group()[last()=1]"/>
</xsl:for-each-group>