嵌套的string-join()表达式

时间:2018-03-11 16:41:55

标签: xml xpath xquery

我有这样的xml:

let $xml :=
 <info>
    <id>1</id>
    <name>one</name>
    <title>t1</title>
</info>
<info>
    <id>2</id>
    <name>two</name>
    <title>t2</title>
</info>
<info>
    <id>3</id>
    <name>three</name>
    <title>t3</title>
</info>
<info>
    <id>4</id>
    <name>four</name>
    <title>t4</title>
</info>

我想将其转换为1,one,t1&2,two,t2&3,three,t3&4,four,t4

我到目前为止所做的并在http://videlibri.sourceforge.net/cgi-bin/xidelcgi上进行了测试是这样的:

let $sources := $xml/info
{
for $out in $sources
 return fn:concat(string-join(string-join(fn:string($out/*),',')),'&amp;')
}

现在我想将它声明为我文件中的一个函数,所以我做了:

declare function local:concatComplexDelimited($ReqNode as node(),
                                              $InnerDilimeter as xs:string,
                                              $OuterDelimiter as xs:string) as xs:string {
let $dsf := $ReqNode/ns1:path/ns1:ToMySequence
for $infx in $dsf
  return fn:concat(fn:string-join(fn:string-join(fn:string($infx/*/text()),$InnerDilimeter)),$OuterDelimiter)
};

它会给出错误string-join() unknown function or number of arguments ..任何人都可以帮助解决问题

1 个答案:

答案 0 :(得分:1)

你的函数声明你将返回一个字符串,但你有一个FLWOR迭代一系列元素并为每个元素生成一个字符串,并将生成一个字符串序列。另外,您要为text()提供一系列fn:string()个节点 - 当用作fn:string-join()的参数时,哪些值应该已经被雾化为字符串。

将其更改为为每个$innerDelimiter元素生成包含<info>的逗号分隔字符串,然后将这些字符串与$OuterDelimiter结合使用。

declare function local:concatComplexDelimited(
  $ReqNode as node(),
  $InnerDelimiter as xs:string,
  $OuterDelimiter as xs:string) 
as xs:string 
{
  fn:string-join(
    for $info in $ReqNode/ns1:path/ns1:ToMySequence
    return 
      fn:string-join($info/*/text(), $InnerDelimiter),
    $OuterDelimiter)
};

如果它有助于使其更具可读性,您可以将内部线分配给变量:

declare function local:concatComplexDelimited(
  $ReqNode as node(),
  $InnerDelimiter as xs:string,
  $OuterDelimiter as xs:string) 
as xs:string 
{
  let $lines :=
      for $info in $ReqNode/ns1:path/ns1:ToMySequence
      return 
        fn:string-join($info/*/text(), $InnerDelimiter)
  return
    fn:string-join($lines, $OuterDelimiter)
};