0

サンプル xml は次のとおりです。

   <?xml version="1.0" encoding="UTF-8" standalone="no"?>
       <check>
        <val>
          <Samsung>
             <name value="galaxy"/>
             <name value="galaxy"/>
             <name value="galaxys"/>
             <id value="123"/>
             <id value="123"/>
             <name2 value="galaxy"/>
           </Samsung>

           <htc>
             <name value="galaxy"/>
             <name value="galaxy"/>
             <name value="galaxys"/>
             <id value="123"/>
             <id value="123"/>
             <name2 value="galaxy"/>
          </htc>
        </val>
     </check>

重複を削除するにはどうすればよいですか?

<name>と値が一致するタグも...また、と<id>以外のタグがさらにある場合、xsltでループを記述する方法は? xsltの書き方がわかりません。助けてください。<Samsung><htc>

出力 xml は次のようになります。

<check>
    <val>
      <Samsung>
         <name value="galaxy"/>
         <name value="galaxys"/>
         <id value="123"/>
         <name2 value="galaxy"/>
       </Samsung>

       <htc>
         <name value="galaxy"/>
         <name value="galaxys"/>
         <id value="123"/>
         <name2 value="galaxy"/>
      </htc>
    </val>
 </check>
4

3 に答える 3

2

重複するノードが常に連続していることを確認できる場合、これを行う最も簡単な方法は、XSTL Identity Transform に基づいて構築し、そのようにテンプレートを取り除くための追加のテンプレートを用意することです。

<xsl:template 
     match="*[not(*)]
             [name() = preceding-sibling::*[1]/name()]
             [@value = preceding-sibling::*[1]/@value]" />

これはすべての子要素に一致し、前の要素と同じ名前と値を持つ場合は無視されます。この場合、要素名をどこにもハードコーディングする必要はありません。

この場合の完全な XSLT は次のとおりです。

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

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

  <xsl:template match="*[not(*)][name() = preceding-sibling::*[1]/name()][@value = preceding-sibling::*[1]/@value]" />
</xsl:stylesheet>

ただし、XML がこのように見え、重複ノードが連続している場合、これは失敗します。

       <Samsung>
         <name value="galaxy"/>
         <name value="galaxys"/>
         <id value="123"/>
         <name value="galaxy"/>
         <id value="123"/>
         <name2 value="galaxy"/>
       </Samsung>

テンプレートを変更して以前のすべてのノードをチェックバックすることで、これを修正できます。

<xsl:template match="*[not(*)]
                      [name() = preceding-sibling::*/name()]
                      [@value = preceding-sibling::*/@value]" />

ただし、これは多数の要素で非効率になり始めます。数百の要素がある場合、各先行兄弟チェックには、数百の要素のチェックが繰り返し含まれます (つまり、100 番目の要素は 99 個の先行要素をチェックする必要があり、101 番目の要素は 100 個の要素をチェックするなど)。

(XSLT1.0 での) より効率的な方法は、Muenchian Groupingと呼ばれる手法を使用することです。XSLT を頻繁に使用する場合、これは確かに学ぶ価値のあるものです。

最初に、要素を「グループ化」するためのキーを定義します。この場合、親、要素名、および値によって定義された個別の要素を探しています。

<xsl:key name="duplicate" match="*[not(*)]" use="concat(generate-id(..), '|', name(), '|', @value)" />

次に、重複を無視するには、指定された「ルックアップ」値のキーの最初の位置に出現しない要素を一致させます

<xsl:template match="*[not(*)]
                      [generate-id() != 
                      generate-id(key('duplicate', concat(generate-id(..), '|', name(), '|', @value))[1])]" />

この場合の完全な XSLT は次のとおりです。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" />
    <xsl:key name="duplicate" match="*[not(*)]" use="concat(generate-id(..), '|', name(), '|', @value)" />

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

 <xsl:template match="*[not(*)][generate-id() != generate-id(key('duplicate', concat(generate-id(..), '|', name(), '|', @value))[1])]" />

</xsl:stylesheet>
于 2013-04-19T13:04:19.543 に答える
1

この変身の時

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

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

<xsl:template match="name">
<xsl:if test="self::name/text()= following-sibling::name/text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="name2">
<xsl:if test="self::name2/text()= following-sibling::name2/text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

以下の XML で実行されます

<?xml version="1.0"?>
<check>
 <val>
    <sai>
     <name> A</name>
     <name> A</name>
    <name2> B</name2>
    <name2> B</name2>
   </sai>
   <dinesh>
    <name> A</name>
    <name> A</name>
    <name2> B</name2>
    <name2> B</name2>
    </dinesh>   
 </val> 
</check>

必要な出力を取得します

<?xml version='1.0' ?>
<check> 
  <val>    
    <sai>     
      <name> A</name>       
      <name2> B</name2>
    </sai>
    <dinesh>
      <name> A</name>
      <name2> B</name2>
    </dinesh>   
   </val> 
</check>
于 2013-04-19T11:13:25.713 に答える
0

@ siva2012 からの回答とほぼ同じです。ただし、名前の子が 1 つしかない場合は、より正確です。

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

    <xsl:template match="name">
        <xsl:variable name="text" select="text()"/>
        <xsl:if test="not(following-sibling::name[text()= $text])" >
            <xsl:copy>
                <xsl:apply-templates select="node()|@*" />
            </xsl:copy>
        </xsl:if>
    </xsl:template>
        <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <xsl:apply-templates  />

    </xsl:template>
</xsl:stylesheet>
于 2013-04-19T11:35:02.737 に答える