1

私はXSLTにまったく慣れておらず、既存のXMLファイルをコピーしようとしていましたが、要素を並べ替えましたが、孫を並べ替えようとすると行き詰まりました。

私がこの入力を持っているとしましょう:

<grandParent>
    <parent> 
        <c>789</c>
        <b>
           <b2>123</b2>
           <b1>456</b1>
        </b>
        <a>123</a>
    </parent>
    ....
</grandParent>

私がやりたいのは、同じXMLファイルを取得することですが、タグの順序をa、b、cに変更し、b = b1、b2の順序にします。そこで、XSLTファイルから始めました。

<xsl:template match="node()|@*">    <- This should copy everything as it is
    <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
</xsl:template>
<xsl:template match="grandParent/parent"> <- parent elements will copy in this order
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:copy-of select="a"/>
        <xsl:copy-of select="b"/>
        <xsl:copy-of select="c"/>
    </xsl:copy>
</xsl:template>

ただし、「xsl:copy-of select = "b"」は、指定されたとおりに要素をコピーします(b2、b1)。「grandParent/parent / b」に別のxsl:templateを使用してみましたが、役に立ちませんでした。

多分私は物事を正しい方法でやっていない...何かヒントはありますか?

ありがとう!

解決策-Nilsに感謝します

あなたのソリューションはうまく機能します。Nilsは、「b」がオプションであり、タグの名前が相関していない可能性がある現在のシナリオに合うように、もう少しカスタマイズしました。最終的なコードは次のようになります。

<xsl:template match="node()|@*">    <- This should copy everything as it is
    <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
</xsl:template>
<xsl:template match="grandParent/parent"> <- parent elements will copy in this order
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:copy-of select="a"/>
                    <xslt:if test="b">
                        <b>
                        <xsl:copy-of select="b1"/>
                        <xsl:copy-of select="b2"/>
                        </b>
                    </xslt:if>
        <xsl:copy-of select="b"/>
        <xsl:copy-of select="c"/>
    </xsl:copy>
</xsl:template>
4

3 に答える 3

1

を使用しxsl:sortます。

次のコードは頭から離れており、機能しない可能性があります。しかし、その背後にある考えは明確でなければなりません。

<xsl:template match="node()|@*">    <- This should copy everything as it is
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
</xsl:template>

<xsl:template match="grandParent/parent"> <- parent elements will copy in this order
    <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:copy-of select="a"/>
    <b>
        <xsl:for-each select="b/*">
            <xsl:sort select="text()" />
            <xsl:copy-of select="." />
        </xsl:for-each>
    </b>
    <xsl:copy-of select="c"/>
    </xsl:copy>
</xsl:template>
于 2013-03-27T12:45:21.827 に答える
1

「grandParent/parent / b」に別のxsl:templateを使用してみましたが、役に立ちませんでした。

<xsl:apply-templates>IDテンプレートがあるので、代わりに使用する必要があります<xsl:copy-of>

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

bこれで、要素に同様のテンプレートを追加できます

<xsl:template match="parent/b">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="b1"/>
        <xsl:apply-templates select="b2"/>
    </xsl:copy>
</xsl:template>

bこれは、存在しない場合をうまく処理しselect="b"ます。要素が見つからない場合、テンプレートは起動しません。

実際、両方の場合で並べ替え順序が同じである場合(要素名のアルファベット順)、2つのテンプレートをを使用する1つに結合して、次<xsl:sort>の完全な変換を行うことができます。

<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="node()|@*">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="grandParent/parent | parent/b">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="*">
        <xsl:sort select="name()" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

(たとえば、指定したXMLの場合@*、XMLには属性が含まれていないため、実際にはビットは必要ありませんが、実際のXMLに属性がある場合でも、そのままにしておいても問題はありません。将来的に追加します)。

于 2013-03-27T12:57:40.830 に答える
1

これが最も一般的な解決策です-xsl:sortテンプレートを使用して-xsl:copy-of特定の名前のハードコーディングはありません

<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="*/*">
     <xsl:copy>
       <xsl:apply-templates select="@*"/>
       <xsl:apply-templates select="node()">
         <xsl:sort select="name()"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメントに適用される場合:

<grandParent>
    <parent>
        <c>789</c>
        <b>
            <b2>123</b2>
            <b1>456</b1>
        </b>
        <a>123</a>
    </parent>
    ....
</grandParent>

必要な正しい結果が生成されます:

<grandParent>
   <parent>
      <a>123</a>
      <b>
         <b1>456</b1>
         <b2>123</b2>
      </b>
      <c>789</c>
   </parent>
    ....
</grandParent>

それでは、XMLドキュメント内のすべての名前を変更しましょう。他の回答はどれもこれでは機能しないことに注意してください

<someGrandParent>
    <someParent>
        <z>789</z>
        <y>
            <y2>123</y2>
            <y1>456</y1>
        </y>
        <x>123</x>
    </someParent>
    ....
</someGrandParent>

同じ変換を適用すると、再び正しい結果が生成されます。

<someGrandParent>
   <someParent>
      <x>123</x>
      <y>
         <y1>456</y1>
         <y2>123</y2>
      </y>
      <z>789</z>
   </someParent>
    ....
</someGrandParent>
于 2013-03-27T13:23:13.030 に答える