私があなたの XML を正しく理解していれば、すべてのグラフは本質的に一連のステップであり、ステップを省略できず、各ステップにはいくつかの選択肢があります。(したがって、グラフを通るパスのセットは、基本的に、さまざまな選択肢のセットのデカルト積です。) そうでない場合、次のことはあなたが望むものではありません。
ここでデカルト積を取得する最も簡単な方法はfor、Jens Erat の最初の回答に示されているように、デカルト積の各要素に対して 1 つの句を含む XQuery FLWOR 式を使用することです。
いくつの要素が存在するかが事前にわからない場合 (グラフで発生する可能性のある「タイプ」値のシーケンスがわからないため)、毎回クエリを新たに定式化したくない場合は、最も簡単な方法は、'Type' 値のシーケンスを 1 つの引数として取り、作業中の 'Root' 要素を別の引数として取り、一度に 1 つの要素を処理する再帰関数を作成することです。
この関数は、サンプル入力に対してその仕事をします:
declare function local:cartesian-product(
  $doc as element(),
  $types as xs:string*
) as xs:string* {
  (: If we have no $types left, we are done.
     Return the empty string. :)
  if (empty($types)) then 
     ''
  (: Otherwise, take the first value off the 
     sequence of types and return the Cartesian
     product of all Words with that type and
     the Cartesian product of all the remaining
     types. :)
  else
     let $t := $types[1],
         $rest := $types[position() > 1]
     for $val in $doc/Word[@Type = $t]/@Value
     for $suffix in 
         local:cartesian-product($doc,$rest)
     return concat($val, $suffix)
  };
残っている唯一の問題は、ドキュメントの順序で異なる「タイプ」値のシーケンスを取得するという、少し難しい問題です。呼び出しdistinct-values($doc//Word/@Type)て値を取得することもできますが、それらがドキュメントの順序になるという保証はありません。
関連する問題に対する Dimitre Novatchev の解決策を借りて、次のように 'Type' 値の適切なシーケンスを計算できます。
let $doc := <Root>
    <Word Type="pre1" Value="A" />
    <Word Type="pre1" Value="D" />
    <Word Type="pre2" Value="G" />
    <Word Type="pre2" Value="H" />
    <Word Type="base" Value="B" />
    <Word Type="post1" Value="C" />
    <Word Type="post1" Value="E" />
    <Word Type="post1" Value="F" />
</Root>
let $types0 := ($doc/Word/@Type),
    $types  := $types0[index-of($types0,.)[1]]
これは、個別の値をドキュメント順に返します。
これで、必要な結果を計算する準備が整いました。
return local:cartesian-product($doc, $types)
結果は、指定した順序とは少し異なる順序で返されます。結果の順序は気にしないと思います。
AGBC AGBE AGBF AHBC AHBE AHBF DGBC DGBE DGBF DHBC DHBE DHBF