1

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つ質問があります。オペランドのテキストはどのように出力されますか?

4

2 に答える 2

0

この代替回答には、同じスタイルシート ロジックがあります (唯一の変更は例番号の説明です) が、例 3 および 4 の編集された質問に対処するために投稿されます。

あなたが持っている場所:

<event>
<example>3</example>
<criteria>
    <or>
        <op>A</op>
        <op>B</op>
    </or>
    <and>
        <op>C</op>
    </and>
</criteria>
</event>

次のように書くと、元のロジックを使用して必要な結果が得られます。

t:\ftemp>type boolean3.xml
<event>
<example>3</example>
<criteria>
  <and>
    <or>
        <op>A</op>
        <op>B</op>
    </or>
    <op>C</op>
  </and>
</criteria>
</event>
t:\ftemp>xslt2 boolean3.xml boolean2.xsl
3 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>

私なら次のように書きます。

t:\ftemp>type boolean4.xml
<event>
  <example>4</example>
  <criteria>
<and>
    <op>A</op>
    <op>B</op>
    <or>
        <op>C</op>
        <op>D</op>
        <op>E</op>
    </or>
</and>
  </criteria>
</event>
t:\ftemp>xslt2 boolean4.xml boolean2.xsl
4 To meet the criteria, event must have A and B and  C or D or E

私のコードでは、オペランドが 2 つある場合にのみ「どちらか」という言葉を使用しましたor... オペランドが 2 つ以上ある場合にも機能すると思いますので、それをor処理ロジックに追加します。

例の番号に対応するように変更されたスタイルシートを次に示します。

t:\ftemp>type boolean2.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

<xsl:output method="text"/>

<!--eat white-space-->
<xsl:template match="text()[not(normalize-space())]"/>

<!--start result-->
<xsl:template match="event">
  <xsl:value-of select="example"/>
  <xsl:text> To meet the criteria, event must have</xsl:text>
  <xsl:apply-templates select="criteria"/>
</xsl:template>

<!--handle conjunction-->
<xsl:template match="and">
  <xsl:for-each select="*">
    <xsl:if test="position()>1"> and</xsl:if>
    <xsl:text> </xsl:text>
    <xsl:apply-templates select="."/>
  </xsl:for-each>
</xsl:template>

<!--handle alternation-->
<xsl:template match="or">
  <xsl:for-each select="*">
    <xsl:if test="position()>1"> or</xsl:if>
    <xsl:text> </xsl:text>
    <xsl:apply-templates select="."/>
  </xsl:for-each>
</xsl:template>

<!--special grammar case for alternation between 2 operands-->
<xsl:template match="or[count(*) = 2]" priority="1">
  <xsl:text> either</xsl:text>
  <xsl:next-match/>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>

したがって、すべては XML の記述方法に依存します。オペランドがどのように機能するかについて、あなたが行ったことをどのように書き直したかを確認し、さらに明確にする必要があるかどうかを尋ねてください.

于 2013-09-05T19:30:10.780 に答える