XML を英文に似たものに変換する必要があります。たとえば、次の XML:
<event>
<criteria>
<and>A</and>
<and>B</and>
<and>
<or>
<and>C</and>
<and>D</and>
</or>
<or>E</or>
</and>
</criteria>
</event>
次のようなものに変換する必要があります。
To meet the criteria event must have A and B and either C and D or E.
これは一例ですが、「and」および「or」条件はさらにネストできます。
ルールは次のようです。
- 要素に後続の兄弟または子がない場合、何も出力されず、完了です。
- 「and」または「or」に子を持たない後続の兄弟がある場合、後続の兄弟のタイプ (「and」または「or」) が出力されます (例: A と B、C と D、D または E)。
- "and" に "or" 子を持つ "and" 兄弟が続く場合、"and either" が出力されます (例: and either C)。
- テキストのない要素は出力されません。
この出力を生成するためにいくつかのアプローチを試みましたが、成功しませんでした。1 つの問題は、再帰が正しく行われていないことです。1 つの要素がネストされている xslt 処理の例をたくさん見てきましたが (たとえば、Item は、他の Item で構成される他の Item で構成することができます)、「and」と「or」のような 2 つの要素の例はありません。 " は兄弟であったり、相互に入れ子になったりすることができます。xsl:template match= "and | or" を使用してから、"and" または "or" をテストしてみましたが、リーフ レベルに到達していないか、順序が間違っています。
このような構造を処理するための正しい方向に誰かが私を向けることができるかどうか、および/または「ブール」文を表すためのより良い構造を誰かが提案できるかどうかを知りたいです。XML はまだファイナライズされていないため、処理が容易になる場合は変更できます。
注: 私は Saxon 9 を使用しており、xslt 2.0 ソリューションを使用できます。
より詳しい情報:
@g-ken-holman に改めて感謝します。提案されたトップダウンのアプローチは気に入っていますが、いくつか問題があります。ケンの例で and/or シーケンスが or/and に変更された理由がわかりません。and/or シーケンスは正しいようです。とにかく、私は例を実行しましたが、うまくいきました。しかし、私は全部で5つのケースを与えられました。最初の 2 つの単純なケースでは、すべてが and か or で、ケース 5 は上記のケースで機能しました。しかし、ケース 3 と 4 は機能しませんでした。XML と結果は次のとおりです。
<event>
<example>3</example>
<criteria>
<or>
<op>A</op>
<op>B</op>
</or>
<and>
<op>C</op>
</and>
</criteria>
</event>
Result: To meet the criteria, event must have either A or B C
Expected: To meet the criteria, event must have either A or B and C
そして例4:
<event>
<example>4</example>
<criteria>
<and>
<op>A</op>
<op>B</op>
</and>
<and>
<or>
<op>C</op>
<op>D</op>
<op>E</op>
</or>
</and>
</criteria>
</event>
結果: 基準を満たすには、イベントに A と BC または D または E が必要です。 期待: 基準を満たすには、イベントに A と B と、C、D または E のいずれかが必要
その理由は、複数の (position()>1) テストがある場合にのみ and/or or が出力されているためだと思います。しかし、これですべてのケースがカバーされるわけではありません。たぶん、position()>1 of node count = 1 の場合でしょうか?
それが簡単になる場合は、「どちらか」の要素を追加できます。
回答時の注意:
これはコメント欄には長すぎるので、ここに追加します。@Ken が答えを提供してくれたと信じており、彼が提案する 2 番目のアプローチが最適です。
処理がわかれば。ドキュメント内のすべてのノードを照合しています。「イベント」に一致し、他のノードの外側にネストされているため、最初に実行されます。次に、「and」ノードが検出された場合、「and」で一致を取得し、そのレベルのすべての「and」兄弟を (for-each) 繰り返し処理します。テスト「position() > 1」が失敗するため、最初のノードの単語「and」は出力しません。xls:text を使用して常に空白を出力します。次に、現在の (コンテキスト) ノードからテンプレートを適用します ()。「and」の子ノードでのみ一致するようになったため、これでツリーをたどり始めます。「and」に一致する場合は、これまで行ったことを繰り返します。次に「or」に一致する場合は、「and」とほとんど同じである match="or" テンプレートを実行します。ただし、「または」という単語を出力します。ただし、"or" および 1]" priority="1"> で一致する 2 つの可能なテンプレートがあります。priority="1" は、優先度が指定されていない限り、他の "or" 一致よりも高い一致の優先度を設定します。 、一致のデフォルトの優先度は 0.5 です。したがって、現在の「or」ノードに 2 つの子がある場合 (or[count(*) > 1])、「either」を出力してから、優先度の低い「or」を許可する呼び出しを呼び出します。実行する一致します。一致のデフォルトの優先度は 0.5 です。したがって、現在の "or" ノードに 2 つの子 (or[count(*) > 1]) がある場合、"either" を出力してから、優先度の低い "or" マッチを実行できるようにする呼び出しを行います。一致のデフォルトの優先度は 0.5 です。したがって、現在の "or" ノードに 2 つの子 (or[count(*) > 1]) がある場合、"either" を出力してから、優先度の低い "or" マッチを実行できるようにする呼び出しを行います。
これは正しいと思いますが、1つ質問があります。オペランドのテキストはどのように出力されますか?