从 XQuery 中的元素和属性有条件地创建格式化字符串
Conditionally creating formatted string from elements and attributes in XQuery
我正在尝试将 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=""
就足够的空括号。
在外部 concat
使用 if
子句(我在答案中添加了一些换行符以提高可读性,您当然可以根据需要删除它们):
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 中间标记插入的隐式换行符,或者您当然可以像以前一样添加它们。
我正在尝试将 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=""
就足够的空括号。
在外部 concat
使用 if
子句(我在答案中添加了一些换行符以提高可读性,您当然可以根据需要删除它们):
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 中间标记插入的隐式换行符,或者您当然可以像以前一样添加它们。