f元素基于属性类型?@ARZ,我想是这样的,但正如您在C.M.Sperberg McQueen的回答中所看到的,当使用不同的值时,顺序是不能保证的。我将发布一个更新,并给出一个更为“SQL”导向的答案,其中我不使用不同的值,而是使用一个(或两个)表变量。这
f元素基于属性类型?@ARZ,我想是这样的,但正如您在C.M.Sperberg McQueen的回答中所看到的,当使用不同的值时,顺序是不能保证的。我将发布一个更新,并给出一个更为“SQL”导向的答案,其中我不使用不同的值,而是使用一个(或两个)表变量。这,sql,xml,sql-server-2008,xquery,Sql,Xml,Sql Server 2008,Xquery,f元素基于属性类型?@ARZ,我想是这样的,但正如您在C.M.Sperberg McQueen的回答中所看到的,当使用不同的值时,顺序是不能保证的。我将发布一个更新,并给出一个更为“SQL”导向的答案,其中我不使用不同的值,而是使用一个(或两个)表变量。这可能更一般,但我不确定属性是否总是按文档顺序出现,因此我选择了一个更一般的解决方案,您可以在其中定义顺序。我猜他会和我的解决方案有同样的问题:MSSQL不支持自定义函数。。。 <Root> <Word Type="pr
f元素基于属性
类型?@ARZ,我想是这样的,但正如您在C.M.Sperberg McQueen的回答中所看到的,当使用不同的值时,顺序是不能保证的。我将发布一个更新,并给出一个更为“SQL”导向的答案,其中我不使用不同的值,而是使用一个(或两个)表变量。这可能更一般,但我不确定属性是否总是按文档顺序出现,因此我选择了一个更一般的解决方案,您可以在其中定义顺序。我猜他会和我的解决方案有同样的问题:MSSQL不支持自定义函数。。。
<Root>
<Word Type="pre1" Value="A" />
<Word Type="pre1" Value="D" />
<Word Type="base" Value="B" />
<Word Type="post1" Value="C" />
<Word Type="post1" Value="E" />
<Word Type="post1" Value="F" />
</Root>
<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>
for $pre in //Word[@Type="pre1"]
for $base in //Word[@Type="base"]
for $post in //Word[@Type="post1"]
return concat($pre/@Value, $base/@Value, $post/@Value)
declare function local:call($prefix as xs:string) as xs:string* {
local:recursion('',
for $value in distinct-values(//Word/@Type[starts-with(., $prefix)])
order by $value
return $value
)
};
declare function local:recursion($strings as xs:string*, $attributes as xs:string*) as xs:string* {
if (empty($attributes))
then $strings
else
for $string in $strings
for $append in //Word[@Type=$attributes[1]]
return local:recursion(concat($string, $append/@Value), $attributes[position() != 1])
};
for $pre in local:call('pre')
for $base in local:call('base')
for $post in local:call('post')
return concat($pre, $base, $post)
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)
};
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)