2011-04-20 9 views
2

私は、次の入力している:値によって要素を並べ替えや削除、重複

<?xml version="1.0" encoding="utf-8"?> 
<NewTerms> 
    <newTerm>XPath</newTerm> 
    <newTerm>AutoValue</newTerm> 
    <newTerm>XPath</newTerm> 
    <newTerm>context</newTerm> 
    <newTerm>AutoValue</newTerm> 
    <newTerm>language files</newTerm> 
    <newTerm>AutoValue</newTerm> 
    <newTerm>.NET</newTerm> 
    <newTerm>XPath</newTerm> 
</NewTerms> 

私はそれをソートしたい、それは次のように完全に機能:私は

<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> 

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

</xsl:stylesheet> 

問題があるを取得しています(明らかに)繰り返しで同じ値を持つ要素(例えばXPath、AutoValue)を持つソートされた出力リスト。私は繰り返し値なしで並べ替えられたリストを持っていたい。つまり、ソートされたXML出力に各値を1回だけ入れたいです。

お願いします。

答えて

2

このスタイルシート:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="kNewTermByValue" match="newTerm" use="."/> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="NewTerms"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:apply-templates 
      select="newTerm[count(.|key('kNewTermByValue',.)[1])=1]"> 
       <xsl:sort/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

出力:

<NewTerms xp_0:noNamespaceSchemaLocation="../XSD\CC-CustomDocuTags.xsd" xmlns:xp_0="http://www.w3.org/2001/XMLSchema-instance"> 
    <newTerm>.NET</newTerm> 
    <newTerm>AutoValue</newTerm> 
    <newTerm>context</newTerm> 
    <newTerm>EPF</newTerm> 
    <newTerm>language files</newTerm> 
    <newTerm>XPath</newTerm> 
</NewTerms> 

:子を出力した後に属性を出力できないため、属性と子を並べ替えないでください。

+0

+1 - 良い答え。私は、セット内の最初のノードをテストする 'count(。key( 'keyName'、。)[1])= 1'メソッドは、IDを比較するよりもずっと面白いと思う)。 –

+0

@lwburk:私はSet Theoryのためにこれも好きです。しかし、それは、両方のオペランドがシングルトンであることを絶対に確信しているときにのみ機能します(誰も空ではありません)。 –

+0

+1すばらしい、私は皆さんからたくさんのことを学んでいます。私の答えが受け入れられたのは残念です。それを再考する方法はありますか(このような解決策を探している他のすべての人にとって、この解決策を指摘することです)? – rekaszeru

1

あなたはの選択あなたの並べ替えをフィルタリングする必要があります。

<xsl:template match="@*|node()[not(preceding::node()=.)]"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"> 
      <xsl:sort select="."/> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

そして、それはあなたに必要な出力与える:

<?xml version="1.0"?> 
<NewTerms> 
    <newTerm>.NET</newTerm> 
    <newTerm>AutoValue</newTerm>AutoValueAutoValue 
    <newTerm>EPF</newTerm> 
    <newTerm>XPath</newTerm>XPathXPath 
    <newTerm>context</newTerm> 
    <newTerm>language files</newTerm> 
</NewTerms> 
+0

ありがとうございました!私はkey()関数を使ってそれをしようとしていました...そしてどこにも到達しませんでした。私はそれが主にbcosだと思うのですが、私は実際にkey()関数がどのように働いて反応するのか分かりませんでした。 – Jasmin

+0

これは属性を削除することに注意してください。また、私は小さな入力のために同じタイプの兄弟をチェックしても構いません。パフォーマンスの違いは目立たないでしょう。しかし、キーを使用することはこれを行うためのより慣用的なXSLT方法であり、大きな入力に対して重大なパフォーマンス上の利点をもたらす可能性があることは注目に値する。私の方針は、鍵を忘れるときには少なくともこれを言及することだと思う。 –