1

私が解決しようとしている問題は、一意のテキスト要素のみを含むすべての要素を取得すると同時に、XSLT シートにパラメーターとして渡された要素名に基づいてノード ツリーを除外することです。

空ではない一意のテキスト要素のみを含むすべてのノードを選択する部分は、比較的簡単でした。

$StartNode//element()/text()[normalize-space(.)]/parent::*

$StartNode、XML ドキュメント内の特定の要素への Xpath 式です。

ここで、結果から特定のノード ツリーを除外することで、いくつかの問題が発生しました。

だから私は次のようなことを望んでいました:

$StartNode//element()/text()[normalize-space(.)]/parent::*[not(ancestor::**$element_to_be_excluded**)]

$element_to_be_excluded は、除外する要素の名前です。

しかし、式のその部分で変数を使用することはできません...

だから私はこの解決策を思いついた

<xsl:variable name="ancestors_of_current_node" as="xs:string*">
   <xsl:sequence select="$current_parent_node/ancestor::*/name()"/>
</xsl:variable>
<xsl:variable name="is_value_in_sequence" as="xs:boolean" select="functx:is-value-in-sequence($exclude_node_local_name, $ancestors_of_current_node)"/>
<xsl:if test="not($is_value_in_sequence)">
    <xsl:call-template name="dataElementMap">
       <xsl:with-param name="node_item" select="$current_parent_node"/>
    </xsl:call-template>
</xsl:if>

functx:is-value-in-sequence は次のとおりです。

<xsl:function name="functx:is-value-in-sequence" as="xs:boolean" xmlns:functx="http://www.functx.com">
  <xsl:param name="value" as="xs:anyAtomicType?"/>
  <xsl:param name="seq" as="xs:anyAtomicType*"/>
  <xsl:sequence select="$value = $seq"/>
</xsl:function>

問題は、この問題を解決するためのよりエレガントな方法があるかどうかです。

ヒントをお寄せいただきありがとうございます。

よろしくVlax

4

3 に答える 3

3

$element_to_be_excluded要素の名前だけの場合は、次を使用します。

$StartNode//element()
             [text()[normalize-space(.)]]
                [not(ancestor::*/name() = $element_to_be_excluded)]

$element_to_be_excludedが 1 つ以上の要素のシーケンスである場合は、次を使用します。

$StartNode//element()
             [text()[normalize-space(.)]]
                [not(ancestor::* intersect $element_to_be_excluded)]

説明:

  1. 不要なものparent::*は排除されます。

  2. true()要素名が指定されている場合、選択した要素の祖先の名前のセットに に含まれる特定の名前が含まれていない場合にのみ、追加の述語を追加し$element_to_be_excludedます。

  3. $element_to_be_excluded1 つ以上の要素のシーケンスが含まれる場合、選択された要素が に含まれる要素の 1 つでない場合にのみ、追加の述語を追加しtrue()ます$element_to_be_excluded

どちらの場合も、1 つの XPath 式を使用して目的の要素を選択できることに注意してください。XSLT 命令を使用する必要はまったくありません。

于 2012-08-02T12:02:37.097 に答える
3

代わりに(あなたが言及したように、変数のために機能しません)

$StartNode//element()/text()[normalize-space(.)]
   /parent::*[not(ancestor::$element_to_be_excluded)]

先祖の名前を確認するために、代わりにこれを試してもらえますか?

$StartNode//element()/text()[normalize-space(.)]
   /parent::*[not(ancestor::*[local-name() = $element_to_be_excluded])]
于 2012-08-02T12:01:03.087 に答える
2

私はいつも as のようなものを書き<xsl:variable name="foo"><xsl:sequence select="someExpression"/></xsl:variable>ます<xsl:variable name="foo" select="someExpression"/>。入力サンプルを見ずに提案をするのは得意ではありませんが、名前付きテンプレートとこれらの 2 つの変数とxsl:ifラップを使用する代わりcall-templateに、モードでテンプレートを使用してコードを記述できるのではないかと思います。

<xsl:apply-templates select=".[not(ancestor::*[local-name() eq $exclude_node_local_name])]" mode="m1"/>

あなたの名前付きテンプレートdataElementMapが例えばに置き換えられます

<xsl:template match="*" mode="m1">...</xsl:template>

(または、より特殊な一致パターン)。

于 2012-08-02T12:01:27.307 に答える