0

for-each ループを使用して XSL ノード セット変数を作成したいと考えています。構築されたノード セットは、コピーではなく元の (選択された) ノード セットであることが重要です。

これは私の問題の非常に単純化されたバージョンです(もちろん選択で解決できますが、それは問題のポイントではありません)。<name> ノードを使用して、構築されたノード セット変数が実際に元のツリーにあり、コピーではないことをテストしました。

XSL バージョン 1.0、プロセッサは msxsl です。

非動作 XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1" omit-xml-declaration="yes" />

<xsl:template match="/">

    <xsl:variable name="entries">
        <xsl:for-each select="//entry">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="entryNodes" select="msxsl:node-set($entries)"/>

    <xsl:for-each select="$entryNodes">
        <xsl:value-of select="/root/name"/>
        <xsl:value-of select="."/>
    </xsl:for-each>

</xsl:template>

</xsl:stylesheet>

XML 入力:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <name>X</name>
    <entry>1</entry>
    <entry>2</entry>
</root>

必要な出力:

X1X2

実際の出力:

12

もちろん、(または) 問題はコピーです。しかし、私はこれを回避する方法を見つけることができません。

4

3 に答える 3

1

for-each ループを使用して XSL ノード セット変数を作成したいと考えています。

それが何を意味するのかわかりません。

構築されたノード セットは、コピーではなく元の (選択された) ノード セットであることが重要です。

この部分は少し理解できたと思います。交換する必要があるようです:

<xsl:variable name="entries">
    <xsl:for-each select="//entry">
        <xsl:copy-of select="."/>
    </xsl:for-each>
</xsl:variable>

と:

<xsl:variable name="entries" select="//entry"/>

または、できれば:

<xsl:variable name="entries" select="root/entry"/>

結果の変数は元のノードのノードセットentryなので、次のように簡単に実行できます。

<xsl:for-each select="$entries">
    <xsl:value-of select="/root/name"/>
    <xsl:value-of select="."/>
</xsl:for-each>

あなたの期待される結果を得るために。

もちろん、変数を必要とせずに、元のコンテキストで元のノードを直接操作することで、同じことを行うことができます。


あなたが行ったコメントに応えて:

ここでは明らかにより良い例が必要ですが、これでどこに行きたいかについて漠然とした考えが得られていると思います. ただし、最初に理解しておく必要があることがいくつかあります。

1.
元のコンテキストでノードのノード セットを含む変数を作成するには、 を使用する必要selectがあります。これにより、選択できる内容が制限されることはありません。選択は一度に、段階的に、またはループ (ここでは実際のループを意味します) で行うことができます。セットを組み合わせることができる任意の方法で、行った中間選択を組み合わせることができます: 結合、交差、または差異。ただし、これらすべてのステップで使用する必要がありselectます。そうしないと、一連の新しいノードが作成され、ソース ツリーでのコンテキストが失われます。

copyIOWとを使用する場合の唯一の違いselectは、前者が新しいノードを作成することです。これはまさに避けたいことです。

2.
xsl:for-eachループではありません。階層や年表はありません。すべてのノードは並行して処理され、現在の反復で前の反復の結果を使用する方法はありません。これは、別の反復の「前」がないためです。

n 個の処理済みノードのそれぞれを既存のノード セットに追加するためにを使用しようとすると、処理済みノードの1 つxsl:for-eachに結合された既存のノード セットをそれぞれ含む n 個の結果が得られます。

3.
XPath 言語は非常に強力であり、示唆する複雑なループを通過することなく、必要なノードを選択できることがわかると思います。

于 2015-02-20T15:08:31.423 に答える
1

XSLT 1.0 には「それを回避する方法」はありません。これは、まさにこれが機能するはずの方法です。ではなくコンテンツで宣言された変数がある場合select、そのコンテンツは、新しく作成されたノードで構成される結果ツリー フラグメントです (それらのノードが元のツリーからのノードのコピーであっても)。元のツリーにアタッチされた元のノードを参照する場合は、を使用して変数を宣言する必要selectがあります。より良い質問は、実際の問題を詳述し、select使用する必要なく必要なノードを見つけるための適切な式を作成する方法を尋ねることです. orfor-eachのほとんどの使用は、適切に構築された述語に置き換えることができます.xsl:ifxsl:choosexsl:key


XSLT 2.0 では、はるかに柔軟です。ノード セットと結果ツリー フラグメントの間に区別はなく、 an の内容はxsl:variable一般的な「シーケンス コンストラクター」として扱われ、それらを構築またはコピーすると、新しいノードを生成できます。

<xsl:variable name="example" as="node()*">
  <xsl:copy-of select="//entry" />
</xsl:variable>

または使用する場合は元のノードxsl:sequence:

<xsl:variable name="example" as="node()*">
  <xsl:sequence select="//entry" />
</xsl:variable>
于 2015-02-20T15:26:46.560 に答える