XSLTの例をいくつか読んで、そのコードを見つけました。
<xsl:apply-template select="@*|node()"/>
どういう意味ですか?
XPath式は、属性ノード()と他のすべてのタイプのXMLノード( )の和集合@* | node()
を選択します。@*
node()
の省略形ですattribute::* | child::node()
。
XSLTでは、XPathはコンテキストノードを基準にしており、デフォルトの選択軸はchild
軸であるため、式
select="..."
します(たとえば、で式として使用される場合<xsl:apply-templates>
)match=""
します(で式として使用される場合<xsl:template>
)。ノードの選択と一致には違いがあることに注意してください。コンテキストノードは選択にのみ関係します。次のノードがコンテキストノードであると想像してください。
<xml attr="value">[
]<child />[
]<!-- comment -->[
]<child>
<descendant />
</child>[
]</xml>
式node()
は、両方の<child>
ノードだけでなく、4つの空白のみのテキストノード(表示のためにで示されます)とコメント[
も選択します。]
が選択され<descendant>
ていません。
XMLの特別な特徴は、属性ノードがそれらが属する要素の子ではないことです(ただし、属性の親はそれが属する要素です)。
この非対称の関係により、それらを個別に選択する必要があります。したがって、@*
。
コンテキストノードに属するすべての属性ノードと一致するため、attr="value"
も選択されます。
|
XPathユニオン演算子です。2つの別々のノードセットから単一のノードセットを作成します。
<xsl:apply-templates>
次に、選択したすべてのノードに適切なものを見つけて<xsl:template>
、そのノードに対して実行します。これは、前述のテンプレートマッチング部分です。
Tomalakの優れた答えに追加するには:
その場合、ほとんどの場合、次<xsl:apply-template select="@*|node()"/>
のようなテンプレートで使用されます。
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
これは、IDルールまたは「IDテンプレート」と呼ばれます。
最も基本的で強力なXSLTデザインパターンの1つは、IDルールの使用とオーバーライドです。
変換がIDルールのみで構成されている場合、変換の結果はソースXMLドキュメント自体になります。これが、テンプレートが「IDルール」と呼ばれる理由です。
なぜこの結果が得られるのですか?
簡単な答えは:XSLT処理モデルのためです。
より詳細な説明は上から始める必要があります:
node()
任意の要素、テキストノード、コメント、または処理命令に一致します。document-(root)-nodeも。と一致しnode()
ます。
任意のドキュメントツリーの「リーフ」ノードを想像できます。これらは、テキストノード、コメント、処理命令など、それ自体に子を持たないノードです。空の要素もリーフノードと見なす必要があります。
IDルールは、最初に、ドキュメントノードのすべての子ノードに対して実行(適用)するために選択されます(これらは、単一の最上位要素と、コメントまたは処理命令の兄弟です)。一致したノードは浅くコピーされ、それが非要素リーフノードである場合、<xsl:apply-templates select="node()|@*"/>
命令はノードまたは属性を選択しません。
一致したノードが要素である場合、それは浅くコピーされ、<xsl:apply-templates select="node()|@*"/>
命令によって同じテンプレートが(変換コードに他のテンプレートがないため)、その各属性とその子ノードのそれぞれに適用されます。
これは、リーフノードまたは属性に到達するまでXMLドキュメントのすべてのノードの処理を駆動し<xsl:apply-templates select="node()|@*"/>
、その場所で子または属性ノードを選択しない再帰です。
@Tomalakの最初の正解おめでとうございます。ダニは彼の答えに行くべきです。彼の答えにいくつかの説明を追加します。
... @ * | node()は...の和集合を選択します
| 演算子は、2つのオペランドの和集合を返すだけでなく、ドキュメント順に並べ替えて重複を削除します。削除する重複がないため、重複排除の部分はここでは関係ありませんが、並べ替えの部分は注目に値します。より正しいバージョンは次のようになります...
... @ * | node()は、ドキュメント順にソートされた...の和集合を選択します。
...および他のすべてのタイプのXML子ノード(node())
これは広く真実ですが、誤解を招く恐れがあります。ほとんどの人が「XML子ノード」を読むとき、彼らはDOMの意味で子ノードを考えます。しかし、これは選択されているものではありません。XDMノードのみが選択されます。説明については、次のドキュメントを参照してください。
<?xml version="1.0" encoding="ISO-8859-1"?>
<root-element my-attrib="myattrib-vaue" xmlns:hi="www.abc.com"><child-element />
abc'def
</root-element>
ここで、コンテキストアイテムが「ルート要素」であると仮定します。Tomalakの答えの読者は、「@ * | node()」によって何が選択されるかという質問をされます。DOMモデルを考えている人にとって、Tomalakの答えが意味することは、次の6つが選択されているということです。
しかし、これはXSLTでは実際には当てはまりません。実際に選択されるのは...
したがって、より正確なステートメントは...
XPath式@*| node()は、(XDMの意味でのコンテキストアイテムの属性ノードとコンテキストアイテムのXML子ノード)の和集合をドキュメント順に選択します。XDモデルは、DOM内にあるエンティティ定義などの一部のノードタイプを無視し、連続するテキストDOMノードは1つのXDMテキストノードに連結されます。