xml - 使用 BaseX/XQuery 将 XML 转换为 CSV
问题描述
我正在尝试将大量 xml 转换为单个 csv 文件。xml 的简化结构如下所示:
<Receipts>
<Receipt>
<Field1 attribute1="a"/>
<Fields2>
<Field2 attribute2="1"/>
<Field2 attribute2="2"/>
</Fields2>
<Field4 attribute4="4a"/>
</Receipt>
<Receipt>
<Field1 attribute1="b"/>
<Field4 attribute4="4b"/>
</Receipt>
<Receipt>
<Field1 attribute1="c"/>
<Fields2>
<Field2 attribute2="3"/>
</Fields2>
<Field3 attribute3="c3"/>
<Field4 attribute4="4c"/>
</Receipt>
</Receipts>
我想获得的 csv 结果是
Attribute1,Attribute2,Attribute3,Attribute4
a,1,,4a
a,2,,4a
b,,,4b
c,3,c3,4c
我的代码基于这个答案,但我只能在 csv 上为每个收据添加一行,并连接所有属性 2,或者只返回包含 Fields2 元素和 Field2 的收据,即:要么:
Attribute1,Attribute2,Attribute3,Attribute4
a,1 2,,4a
b,,,4b
c,3,c3,4c
或这个:
Attribute1,Attribute2,Attribute3,Attribute4
a,1,,4a
a,2,,4a
c,3,c3,4c
我的第一种情况的代码是:
declare option output:method "csv";
declare option output:csv "header=yes, separator=comma";
declare context item := document {<Receipts>
<Receipt>
<Field1 attribute1="a"/>
<Fields2>
<Field2 attribute2="1"/>
<Field2 attribute2="2"/>
</Fields2>
<Field4 attribute4="4a"/>
</Receipt>
<Receipt>
<Field1 attribute1="b"/>
<Field4 attribute4="4b"/>
</Receipt>
<Receipt>
<Field1 attribute1="c"/>
<Fields2>
<Field2 attribute2="3"/>
</Fields2>
<Field3 attribute3="c3"/>
<Field4 attribute4="4c"/>
</Receipt>
</Receipts>};
for $x in //Receipt
return
<csv>
<record>
<Attribute1>{$x/Field1/@attribute1/data()}</Attribute1>
<Attribute2>{$x/Fields2/Field2/@attribute2/data()}</Attribute2>
<Attribute3>{$x/Field3/@attribute3/data()}</Attribute3>
<Attribute4>{$x/Field4/@attribute4/data()}</Attribute4>
</record>
</csv>
对于第二种情况,它将是:
declare option output:method "csv";
declare option output:csv "header=yes, separator=comma";
declare context item := document {<Receipts>
<Receipt>
<Field1 attribute1="a"/>
<Fields2>
<Field2 attribute2="1"/>
<Field2 attribute2="2"/>
</Fields2>
<Field4 attribute4="4a"/>
</Receipt>
<Receipt>
<Field1 attribute1="b"/>
<Field4 attribute4="4b"/>
</Receipt>
<Receipt>
<Field1 attribute1="c"/>
<Fields2>
<Field2 attribute2="3"/>
</Fields2>
<Field3 attribute3="c3"/>
<Field4 attribute4="4c"/>
</Receipt>
</Receipts>};
for $x in //Receipt for $y in $x/Fields2/Field2
return
<csv>
<record>
<Attribute1>{$x/Field1/@attribute1/data()}</Attribute1>
<Attribute2>{$y/@attribute2/data()}</Attribute2>
<Attribute3>{$x/Field3/@attribute3/data()}</Attribute3>
<Attribute4>{$x/Field4/@attribute4/data()}</Attribute4>
</record>
</csv>
解决方案
经过更深入的搜索,我找到了解决方案。在第二个 for 循环的第二个选项上,您应该添加该allowing empty
函数,以便代码最终看起来像这样:
declare option output:method "csv";
declare option output:csv "header=yes, separator=comma";
declare context item := document {<Receipts>
<Receipt>
<Field1 attribute1="a"/>
<Fields2>
<Field2 attribute2="1"/>
<Field2 attribute2="2"/>
</Fields2>
<Field4 attribute4="4a"/>
</Receipt>
<Receipt>
<Field1 attribute1="b"/>
<Field4 attribute4="4b"/>
</Receipt>
<Receipt>
<Field1 attribute1="c"/>
<Fields2>
<Field2 attribute2="3"/>
</Fields2>
<Field3 attribute3="c3"/>
<Field4 attribute4="4c"/>
</Receipt>
</Receipts>};
for $x in //Receipt for $y allowing empty in $x/Fields2/Field2
return
<csv>
<record>
<Attribute1>{$x/Field1/@attribute1/data()}</Attribute1>
<Attribute2>{$y/@attribute2/data()}</Attribute2>
<Attribute3>{$x/Field3/@attribute3/data()}</Attribute3>
<Attribute4>{$x/Field4/@attribute4/data()}</Attribute4>
</record>
</csv>
返回委托人 CSV:
Attribute1,Attribute2,Attribute3,Attribute4
a,1,,4a
a,2,,4a
b,,,4b
c,3,c3,4c
推荐阅读
- sql-server - SSIS:如何在包完成后自动重新运行包?
- linux - 如何在bash中获取映射到docker容器的特定主机名的所有IP地址
- python - keras 中的 kullback_leibler_divergence
- c# - 在 Tag helper .net core 中设置默认值
- assembly - (MIPS 汇编程序)我们可以自己初始化程序计数器吗?
- visual-studio-2017 - VS 2017 和 Resharper 颜色
- python - 计算 Numba 中 numpy 数组中非零值的数量
- python - 美丽的汤查找和导航 HTML
- algorithm - 算法混乱
- excel - 在 VBA 中无法通过名称从外部程序传递变体参数