1

XML ドキュメントに繰り返しノードが含まれているシナリオがあります。そのようなノードをすべて取り除きたいです。これは「重複の削除」ではないことに注意してください。複数回発生しているノードのすべてのエントリを完全に削除したいと考えています。

Ex My 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。しかし、このスニペットの書き方がわかりません。

4

3 に答える 3

2

これはあなたが必要とすることをします。

に対して同じ値を持つ親の子がUserOBS1 つだけ存在するかどうかをチェックする要素のテンプレートがあります。その場合、ノード全体が出力にコピーされます。UserOBSUserObjectId

<?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>
于 2013-05-04T22:12:02.690 に答える
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>
于 2013-05-05T02:29:33.497 に答える
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>
于 2013-05-05T07:55:50.067 に答える