根据XQuery中的元素和属性有条件地创建格式化字符串

根据XQuery中的元素和属性有条件地创建格式化字符串,xquery,Xquery,我正在尝试将xml文档转换为特定的选项卡分隔平面文件结构。大多数元素都可以映射到单列,或者使用fn:string-join()简单地连接起来,但是我有一些元素的映射更复杂。示例元素如下所示: <record> <details> <passports> <passport country="">0018061/104</passport> <passport country="UK">03

我正在尝试将xml文档转换为特定的选项卡分隔平面文件结构。大多数元素都可以映射到单列,或者使用fn:string-join()简单地连接起来,但是我有一些元素的映射更复杂。示例元素如下所示:

<record>
  <details>
    <passports>
      <passport country="">0018061/104</passport>
      <passport country="UK">0354761445</passport>
      <passport country="USA">M001806145</passport>
    </passports>
  </details>
<record>
  0018061/104;(UK) 0354761445;(USA) M001806145
因此,如果
@country
属性不是
,则将其放入
()
,否则将忽略它。元素值如下,每个元素之间用
分隔

以下是我迄今为止所做的工作:

for $record in //record
  return concat($record/@uid/string(),
  (: ... other columns ... :)
  "&#09;", <S>{for $r in //$record/details/passports/passport
    return concat("(", $r/@country, ") ", $r, ";")}</S>/string()
  ,"&#10;")

理想情况下,我想知道这样做的正确方法,否则只需删除
@country=”“
中的空括号就足够了。

在外部
concat
中使用
if
子句(我在答案中添加了一些新行以提高可读性,您当然可以随意删除它们):

查询的新结果:

0018061/104; (UK) 0354761445; (USA) M001806145;
也可以使用隐式循环

/record/details/passports/passport/string-join(
  (
    "&#09;",
    if (@country != "")
    then "(" || @country || ") "
    else (),
    .
  ), ""
)
或者显式循环结果,仍然有一个更干净的查询(通过用相应的
concat(…)
调用替换串联运算符
|
,您将保持XQuery 1.0的兼容性):


这两种情况都使用BaseX在标记之间插入的隐式换行符,或者您当然可以像以前一样添加它们。

在外部
concat
中使用
if
子句(我在答案中添加了一些换行符以提高可读性,您当然可以根据需要删除它们):

查询的新结果:

0018061/104; (UK) 0354761445; (USA) M001806145;
也可以使用隐式循环

/record/details/passports/passport/string-join(
  (
    "&#09;",
    if (@country != "")
    then "(" || @country || ") "
    else (),
    .
  ), ""
)
或者显式循环结果,仍然有一个更干净的查询(通过用相应的
concat(…)
调用替换串联运算符
|
,您将保持XQuery 1.0的兼容性):



这两种情况都使用BaseX在标记之间插入的隐式换行符,或者您当然可以像以前一样添加它们。

请提供适合您发布的查询的示例输入(此处缺少包装记录和详细信息标记)。请提供适合您发布的查询的示例输入(此处缺少包装记录和详细信息标记)。请提供适合您发布的查询的示例输入(此处缺少包装记录和详细信息标记)。谢谢。我试过一个if语句,但我一定是在语法上做错了什么。这很好,谢谢。顺便问一下-有没有更好的方法避免使用循环或添加周围的?你使用的是什么查询处理器,它支持XQuery 3.0吗?BaseX 8.2-我相信它不支持XQuery 3,是的。我添加了一些建议以下是您如何获得灵感的结果。您需要
元素的原因是
for
循环返回一个字符串序列,而不是单个字符串;您可以使用
字符串连接($seq,“”)
(同时用已有的循环替换
$seq
).注意,答案似乎表明“隐式循环”是XQuery 3.0的功能,不是。谢谢。我试过一个if语句,但我一定是在语法上做了一些错误。这很好,谢谢。顺便问一下-有没有更好的方法避免使用循环或添加周围的?你使用的是什么查询处理器,它支持XQuery 3.0吗?BaseX 8.2?我相信它支持BaseX supports XQuery 3,是的。我添加了一些建议,说明如何获得灵感的结果。之所以需要
元素,是因为
for
循环返回一个字符串序列,而不是单个字符串;您可以使用
字符串联接($seq,”)
(将
$seq
替换为已有的循环)。注意,答案似乎表明“隐式循环”是XQuery 3.0的功能,不是。谢谢。我试过一个if语句,但我一定是在语法上做了一些错误。这很好,谢谢。顺便问一下-有没有更好的方法避免使用循环或添加周围的?你使用的是什么查询处理器,它支持XQuery 3.0吗?BaseX 8.2?我相信它支持BaseX supports XQuery 3,是的。我添加了一些建议,说明如何获得灵感的结果。之所以需要
元素,是因为
for
循环返回一个字符串序列,而不是单个字符串;您可以使用
字符串联接($seq,”)
(将
$seq
替换为已有的循环)。注意,答案似乎表明“隐式循环”是XQuery 3.0功能,而不是。
for $record in /record/details/passports/passport
return (
  "&#09;" || (
    if ($record/@country != "")
    then "(" || $record/@country || ") "
    else ()
  ) || $record
)