10

単純なこととして始まったものは、XSLTnoobにとって非常に厄介であることが判明しました。

子ノード/降順をソートしようとしていますが、親ノードに属性を追加した後、VS2010でデバッグするときにエラーが発生します。

"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があるとします。

<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>

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

したがって、明確にするために、私は1つの<year>ノード内での並べ替えにのみ関心があります。

ノードを別々のノードに分割する前(つまり、xmlは/ posts / postでした)、次の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が明らかに返されます(変換なし)

質問:親ノード属性()に対応するために上記の(または新しい)XSLTを更新する方法は<year value="">?調査の結果、「要素作成の前に属性作成を追加する必要がある」との回答がありました。これは、デバッガーを監視するのと同じように意味があります。子ノードはdesc順に形成されますが、yearタグにはその属性がありません。しかし、私はXSLTについて本当に手がかりを持っていません。複雑すぎるのはわかりませんが、言語がわからないだけです。

どんな助けでも、大いに感謝します。ありがとう

4

2 に答える 2

11

つまり、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>

上記の方が良いアプローチだと思いますが、エラーの根本的な原因は、並べ替えを行ったときに属性が要素と混ざっていたことにあると思います。これを行うだけで、元のXSLTはおそらくエラーなしで実行されます。

<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>
于 2013-02-01T13:58:49.483 に答える
2

この変換

<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>

提供されたXMLドキュメントに適用した場合:

<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>

必要な正しい結果を生成します。

<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>
于 2013-02-01T14:04:36.067 に答える