3

次の XSLT フラグメントは、最初と最後のテキスト ノードを特定の @audience 属性でラップ/タグ付けして強調表示するために使用されます。

<xsl:template match="text()">
    <xsl:if test=". = ((((ancestor::*[contains(@audience,'FLAG_')])[last()])/descendant::text())[1])">                  
        <xsl:call-template name="flagText"/>            
    </xsl:if>
    <xsl-value-of select="."/>
    <xsl:if test=". = ((((ancestor::*[contains(@audience,'FLAG_')])[last()])/descendant::text())[last()])">                 
        <xsl:call-template name="flagText"/>            
    </xsl:if>
</xsl:template>

疑似コード:
フラグ基準に一致する最後の (最も近い) 祖先要素を見つけてから、その要素の子孫である最初と最後のテキスト ノードを見つけてフラグを立てます。

ロジックは正しいが、実装が間違っている。これは確かに最初と最後のテキストノードを見つけますが、ノードではなく値を照合しています。これは、最初または最後のノードと同じ値を持つテキスト ノードにフラグを立てます。


The quick brown fox jumped over the lazy dog.

現在の出力:
[FLAG]The quick brown fox jumped over [FLAG]the lazy dog[FLAG].

[1] と犬の [last()] は適切にフラグが立てられていますが、最初の文字列と一致するか等しいため、途中で「the」という単語も検出されます。

編集:
期待される(望ましい)出力:
[FLAG]The quick brown fox jumped over the lazy dog.[FLAG]

最初と最後のノードのみに一致するようにステートメントを再編成するにはどうすればよいですか? 文字列を比較したくありません。最初と最後を選択したいだけです。

編集:

ソース XML の例

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept audience="Users" id="concept_lsy_5vg_kl"><title>Product ABC</title><conbody><p>This is a blurb about <ph>Product ABC</ph>. Since the text in the phrase (ph) matches the text node in the title (first text node) it will be flagged. I only want the first and last nodes flagged. Basically, I don't want to compare the contents of the nodes. <ph audience="Users">I also need to support inline cases such as this one. </ph>I just want the flags before and after the first and last text nodes for each audience match.</p></conbody></concept>

XSLT の例

<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >

    <xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="text()">
        <xsl:if test=". = ((((ancestor::*[contains(@audience,'Users')])[last()])/descendant::text())[1])">          
            <xsl:text>[USERS]</xsl:text>            
        </xsl:if>
        <xsl:value-of select="."/>
        <xsl:if test=". = ((((ancestor::*[contains(@audience,'Users')])[last()])/descendant::text())[last()])">         
            <xsl:text>[/USERS]</xsl:text>           
        </xsl:if>
    </xsl:template> 



</xsl:stylesheet>

電流出力

[USERS]製品 ABC これは、[USERS]製品 ABC に関する宣伝文句です。フレーズ (ph) のテキストは、タイトルのテキスト ノード (最初のテキスト ノード) と一致するため、フラグが立てられます。最初と最後のノードにフラグを付けたいだけです。基本的に、ノードの内容を比較したくありません。[USERS]このようなインライン ケースもサポートする必要があります。[/USERS]各オーディエンス マッチの最初と最後のテキスト ノードの前後にフラグが必要です。[/USERS]

望ましい出力 [USERS]製品 ABCこれは、製品 ABC に関する宣伝文句です。フレーズ (ph) のテキストは、タイトルのテキスト ノード (最初のテキスト ノード) と一致するため、フラグが立てられます。最初と最後のノードにフラグを付けたいだけです。基本的に、ノードの内容を比較したくありません。[USERS]このようなインライン ケースもサポートする必要があります。[/USERS]各オーディエンス マッチの最初と最後のテキスト ノードの前後にフラグが必要です。[/USERS]

ありがとう。

4

2 に答える 2

1

あなたの式では、あなたがいるテキストノードのクラス名が「Users」の「最後の」祖先を取得しています

...(ancestor::*[contains(@audience,'FLAG_')])[last()])...

しかし、あなたは本当にここで最初のものを手に入れたいと思っています. つまり、直近の祖先です。祖先のリストは、親ノードから始まり、次に祖父母など...

...(ancestor::*[contains(@audience,'FLAG_')])[1])...

さらに、文字列を比較したくないと言います。テキストノードが最初か最後かを調べるだけですが、現在の比較は文字列をチェックしています。そのため、同じテキストを持つ 2 つのテキスト ノード (そのうちの 1 つが最初のもの) がある場合、不正な '[USER]' タグを取得します。2 つのノードが同じノードであるかどうかをテストするには (単に同じコンテンツを持っているのではなく)、generate-id 関数を使用できます。

generate-id() = generate-id(((ancestor::*[contains(@audience,'Users')][1])/descendant::text())[1])

このXSLTを試してください

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
  <xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="text()">
    <xsl:if test="generate-id() = generate-id(((ancestor::*[contains(@audience,'Users')][1])/descendant::text())[1])">
      <xsl:text>[USERS]</xsl:text>
    </xsl:if>
    <xsl:value-of select="."/>
    <xsl:if test="generate-id() = generate-id(((ancestor::*[contains(@audience,'Users')][1])/descendant::text())[last()])">
      <xsl:text>[/USERS]</xsl:text>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

しかし....別のアプローチを取ることができるかもしれません。XML と予想される出力を純粋に見て、取ることができる別のアプローチは、「users」クラスの任意の要素に一致するテンプレートを用意し、 xslを使用して開始と終了の [USER] タグを単純に書き出すことです。すべてのテキストを選択するには、間にapply-templatesを挿入します。

代わりに、次の XSLT を試してください。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
  <xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="*[contains(@audience,'Users')]">
    <xsl:text>[USERS]</xsl:text>
      <xsl:apply-templates />
    <xsl:text>[/USERS]</xsl:text>
  </xsl:template>
</xsl:stylesheet>
于 2013-09-06T07:27:07.650 に答える
1

基本的な質問ですみませんが、@audience が users に設定されているときにテキストを強調表示するために ditaval ファイルを使用しない理由がわかりませんか? レビュアーがテキストを見つけて確認できるように、基本的にテキストに色を付けることができます。レビューが終わったら、ハイライトをオフにするだけです。

多分私はあなたの意図を誤解しています。

于 2013-09-06T02:30:12.097 に答える