2013-02-01 17 views
7

簡単なことから始めたのはXSLT noobにとって非常に面倒です。XSLTソート - 属性を持つ親ノード内でxml子ノードをソートする方法

VS2010でデバッグするときに彼らの親ノードに属性を追加した後、私はエラーを受け取り、降順/のchildNodesを並べ替えるしようとしているが、:

<posts> 
    <year value="2013"> 
     <post postid="10030" postmonth="1"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10040" postmonth="2"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10050" postmonth="3"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
    </year> 
    <year value="2012"> 
     <post postid="10010" postmonth="1"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10015" postmonth="2"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10020" postmonth="3"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
    </year> 
</posts> 

"Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added."

は、私はこの単純なXMLがあるとし

xmldatasourceにXPATHを渡して、関連する<year>ノードを取得します。 2013. 次に、<post>の子ノードをpostidを使用して降順に並べ替える必要があるため、<year value=2013>の場合は、レンダリング時に最初にpostid = 10050が表示されます。

したがって、明確にするには、ノード<year>のソートにのみ関心があります。

私は別々のノードにノードを分割する前に(すなわち、XMLがあった/ポスト/ポスト)は、以下のXSLTが働いた:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"> 
       <xsl:sort select="@postid" data-type="text" order="descending"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

を伴う上記のエラーを実行しているとき今xmldatasourceが空です。昇順で昇順を渡すと、同じXMLが明らかに返されます(変換なし)

質問:親ノードの属性(<year value="">)に対応するようにXSLTを更新するにはどうすればよいですか?研究を通じて、「要素作成の前に属性作成を追加する必要があります」と答えました。これは、デバッガを見ていると意味があり、子ノードはdescの順に形成されますが、yearタグにはその属性がありません。しかし、私は本当にXSLTについてのヒントはありません。あまりにも複雑すぎるとは見えませんが、言語を知らないだけです。

ご協力いただきありがとうございます。ありがとう

答えて

5

あなたはXML文書の一部(1つの<year>ノード)をXSLTプロセッサに渡すだけであると言っていますか?

ソートを使用する唯一のテンプレートであるように、年単位で別のテンプレートを使用する必要があります。どのように以下の通りです:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="year"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*" /> 
     <xsl:apply-templates select="post"> 
     <xsl:sort select="@postid" data-type="number" order="descending"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

私は上記より良いアプローチだと思うが、私はあなたのエラーの根本的な原因は、それはそれはソートをした要素を持つの属性を混入していることだと思います。

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"> 
     <xsl:apply-templates select="node()"> 
      <xsl:sort select="@postid" data-type="text" order="descending"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 
+0

これだけです。それは素晴らしいです。そんなにありがとう! はい私は1年ノードをXSLTに渡すだけです。私は表示したい年/記事を選択します。 新しい構造を見つけて、xsltを読むことを試みます。 – JimXC

+0

この場合、なぜ 'data-type =" text "'を使用するのでしょうか? 'postid'の値の長さが違うと、明らかに間違った結果になります。 –

+0

それは良い点です。 JimXCのオリジナルのXSLTが使用したものであり、彼の質問の焦点では​​なく、例のIDが数字であることに気付かなかったので、私はそれを使用しました。 IDが数値であることが保証されている場合は、 'data-type =" numeric "が望ましいでしょう。 – JLRishe

2

この変換:あなたは、単にこれをしなかった場合は、元のXSLTは、おそらく、エラーなしで実行します

<posts> 
    <year value="2013"> 
     <post postid="10030" postmonth="1"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10040" postmonth="2"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10050" postmonth="3"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
    </year> 
    <year value="2012"> 
     <post postid="10010" postmonth="1"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10015" postmonth="2"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
     <post postid="10020" postmonth="3"> 
      <othernode></othernode> 
      <othernode2></othernode2> 
     </post> 
    </year> 
</posts> 

:提供されるXML文書に適用さ

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="year"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="@postid" data-type="number" order="descending"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

は、欲しい、正しい結果をもたらす:

<posts> 
    <year value="2013"> 
     <post postid="10050" postmonth="3"> 
     <othernode/> 
     <othernode2/> 
     </post> 
     <post postid="10040" postmonth="2"> 
     <othernode/> 
     <othernode2/> 
     </post> 
     <post postid="10030" postmonth="1"> 
     <othernode/> 
     <othernode2/> 
     </post> 
    </year> 
    <year value="2012"> 
     <post postid="10020" postmonth="3"> 
     <othernode/> 
     <othernode2/> 
     </post> 
     <post postid="10015" postmonth="2"> 
     <othernode/> 
     <othernode2/> 
     </post> 
     <post postid="10010" postmonth="1"> 
     <othernode/> 
     <othernode2/> 
     </post> 
    </year> 
</posts> 
+0

これも確認済みです。 また、自分の利益のために、あなたはデータ型で数字を使用しています。しかし以前のポスターは、apply-templateでselect = postを使っていましたが、*を使っています。違いは何ですか?名前付きノードをケータリングしていると仮定すると、他のノードはポスト固有であると仮定します。 – JimXC

+1

@JimXC、現在のノードの子要素が 'post'であることがわかっているときはいつでも、' * 'を使うと、XSLTプロセッサによる子ノードが' post'かどうかのチェックを避けることができます。また、コードはこのように短く、書込みはより速く簡単です。 –

+0

ありがとうございました。私は恐れてupvoteまたは+1することはできません。 – JimXC

関連する問題