我正在尝试将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 ... :)
"	", <S>{for $r in //$record/details/passports/passport
return concat("(", $r/@country, ") ", $r, ";")}</S>/string()
," ")
我确信这是一种更简单的方法,但这几乎可以完成工作 - 它会产生:
() 0018061/104;(UK) 0354761445;(USA) M001806145
理想情况下,我想知道正确的方法,否则只需删除@country=""
就足够的空括号。
答案 0 :(得分:0)
在外部if
中使用concat
子句(为了更好的可读性,我添加了一些换行符,您当然可以根据需要删除它们):
concat(
if ($r/@country != "")
then concat("(", $r/@country, ") ")
else "",
$r,
";"
)
查询的新结果:
0018061/104; (UK) 0354761445; (USA) M001806145;
您也可以进行隐式循环
/record/details/passports/passport/string-join(
(
"	",
if (@country != "")
then "(" || @country || ") "
else (),
.
), ""
)
或显式循环结果并仍然有一个更清晰的查询(通过相应的||
调用替换连接运算符concat(...)
,您将保持XQuery 1.0兼容):
for $record in /record/details/passports/passport
return (
"	" || (
if ($record/@country != "")
then "(" || $record/@country || ") "
else ()
) || $record
)
这两种情况都使用BaseX在令牌之间插入的隐式换行符,或者你可以像以前一样添加它们。