XQuery/解析 CSV
外观
< XQuery
您希望将逗号分隔值 (CSV) 文本文件解析成 XML 结构,或者您有一个具有非常类似行/字段结构的平面文件,您希望将其转换为 XML 格式。
我们将使用 tokenize($input, '\n') 函数将输入文件分解成单独的行。然后,我们将使用 tokenize($input, '\s*,\s*') 函数将每行解析成单独的字段。正则表达式 \s* 将删除空格。
xquery version "1.0";
let $csv-input-sample :=
'John, Smith, x123
Peg, Jones , x456
Sue, Adams , x789
Dan, McCoy , x321'
let $lines := tokenize($csv-input-sample, '\n')
return
<results>{
for $line in $lines
let $fields := tokenize($line, '\s*,\s*')
return
<row>{
for $field in $fields
return
<field>{$field}</field>
}</row>
}</results>
<results>
<row>
<field>John</field>
<field>Smith</field>
<field>x123</field>
</row>
<row>
<field>Peg</field>
<field>Jones</field>
<field>x456</field>
</row>
<row>
<field>Sue</field>
<field>Adams</field>
<field>x789</field>
</row>
<row>
<field>Dan</field>
<field>McCoy</field>
<field>x321</field>
</row>
</results>
第二个示例将使用 CSV 文件的第一行作为每列的每个元素名称的数据字典。
xquery version "1.0";
let $csv :=
'name,faculty
alice,anthropology
bob,biology'
let $lines := tokenize($csv, '\n')
let $head := tokenize($lines[1], ',')
let $body := remove($lines, 1)
return
<people>
{
for $line in $body
let $fields := tokenize($line, ',')
return
<person>
{
for $key at $pos in $head
let $value := $fields[$pos]
return
element { $key } { $value }
}
</person>
}
</people>
<people>
<person>
<name>alice</name>
<faculty>anthropology</faculty>
</person>
<person>
<name>bob</name>
<faculty>biology</faculty>
</person>
</people>
很多时候,您会有一系列 CSV 文件,它们可能都具有非常相似的导入选项。在这种情况下,能够将一系列配置参数传递给单个 XQuery 函数非常有用。这些配置参数包括:
- 字段分隔符是什么(默认为逗号)
- 根节点的元素名称
- 每行或每行的元素名称
<file-import-config>
<field-separator>,<field-separator>
<root-element-name>people</root-element-name>
<line-element-name>person</line-element-name>
</file-import-config>
然后,您可以在 CSV 解析器中使用此配置文件。
xquery version "1.0";
let $config :=
<file-import-config>
<field-separator>:</field-separator>
<root-element-name>People</root-element-name>
<line-element-name>Person</line-element-name>
</file-import-config>
let $csv :=
'name:faculty
alice:anthropology
bob:biology'
let $lines := tokenize($csv, '\n')
let $head := tokenize($lines[1], $config/field-separator)
let $body := remove($lines, 1)
return
element {$config/root-element-name}
{
for $line in $body
let $fields := tokenize($line, $config/field-separator)
return
element {$config/line-element-name}
{
for $key at $pos in $head
let $value := $fields[$pos]
return
element { $key } { $value }
}
}
上面的代码假设了一种简单的 CSV 格式。在实际应用中,CSV 必须处理更复杂的情况,对于这些情况,简单的使用 tokeniser() 不足以解析一行。包含一个或多个分隔符的字符串将用双引号括起来。引号内的引号也需要处理。
以下实现处理了部分或全部这些复杂情况,尽管通常不清楚考虑了哪些复杂情况。
- 用于将 CSV 文件转换为 XML 的 XSLT 2.0 样式表
- Matthew Royal 的解析器 遗憾的是,由于它使用可变映射,因此它仅适用于 Marklogic。
- Zorba CSV 导入器
- BaseX CSV 模块
- David Cassel 另一个特定于 Marklogic 的实现