![从 xml 文件创建 CSV](https://linux22.com/image/213111/%E4%BB%8E%20xml%20%E6%96%87%E4%BB%B6%E5%88%9B%E5%BB%BA%20CSV.png)
我正在尝试从 xml 创建一个 csv,其中仅包含 xml 中的一些信息。
这是我的 xml:
<?xml version="1.0" encoding="UTF-8"?>
<hashlist version = "2.0" xmlns = "urn:ASC:MHL:v2.0">
<creatorinfo>
<creationdate>2022-11-06T01:22:14+00:00</creationdate>
<hostname>MacBook-Pro-de-Baptiste.local</hostname>
<tool>ARRI HDET job</tool>
</creatorinfo>
<processinfo>
<process>in-place</process>
</processinfo>
<hashes>
<hash>
<path size="3435540600" lastmodificationdate="2022-11-06T01:21:00+00:00">A_0900C001_220927_102036_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:21:00+00:00">3f93f215ec277fc7</xxh64>
</hash>
<hash>
<path size="3280802936" lastmodificationdate="2022-11-06T01:21:14+00:00">A_0900C002_220927_102120_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:21:14+00:00">6a3c2be7577f31bd</xxh64>
</hash>
<hash>
<path size="2657895544" lastmodificationdate="2022-11-06T01:21:26+00:00">A_0900C003_220927_102240_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:21:26+00:00">6606cf4d3b1ebc17</xxh64>
</hash>
<hash>
<path size="4988562588" lastmodificationdate="2022-11-06T01:21:49+00:00">A_0900C004_220927_102334_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:21:49+00:00">cd0a2dca6f8f6c21</xxh64>
</hash>
<hash>
<path size="633346644" lastmodificationdate="2022-11-06T01:21:52+00:00">A_0900C005_220927_102506_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:21:52+00:00">e617e05dae72e5a6</xxh64>
</hash>
<hash>
<path size="3889553016" lastmodificationdate="2022-11-06T01:22:13+00:00">A_0900C006_220927_102615_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:22:13+00:00">d6e487264d1246b0</xxh64>
</hash>
<hash>
<path size="273064020" lastmodificationdate="2022-11-06T01:22:14+00:00">A_0900C007_220927_102720_a1BZ0_hde.mxf</path>
<xxh64 action="original" hashdate="2022-11-06T01:22:14+00:00">80f5f5683e1f326d</xxh64>
</hash>
</hashes>
</hashlist>
我想要这样的东西:
A_0900C001_220927_102036_a1BZ0_hde.mxf;3f93f215ec277fc7
A_0900C002_220927_102120_a1BZ0_hde.mxf;6a3c2be7577f31bd
ETC...
我试过了
xmllint --xpath '/hashlist/hashes/hash/path/text()' file.xml
但返回的是“XPath 设置为空”
答案1
我的xmllint
-foo 有点生疏,特别是在正确使用命名空间方面,所以我可能会使用xmlstarlet
:
xmlstarlet sel -N ns='urn:ASC:MHL:v2.0' --template \
--match '/ns:hashlist/ns:hashes/ns:hash' \
--value-of 'concat(ns:path, ";", ns:xxh64)' --nl \
file.xml
这通过绝对路径匹配每个节点,然后输出其值和子节点hash
的值的串联,它们之间有一个 in(后跟一个换行符)。path
xxh64
;
由于文档使用隐式命名空间,因此我们需要使用文档根元素中的命名空间声明显式命名空间前缀,然后使用它为 XPath 表达式中的每个节点名称添加前缀。
然而,下面的评论(现已删除)指出,xmlstarlet
允许使用名为 的匿名包罗万象的命名空间_
:
xmlstarlet sel --template \
--match '/_:hashlist/_:hashes/_:hash' \
--value-of 'concat(_:path, ";", _:xxh64)' --nl \
file.xml
给定问题中的 XML,上述任一命令都会生成
A_0900C001_220927_102036_a1BZ0_hde.mxf;3f93f215ec277fc7
A_0900C002_220927_102120_a1BZ0_hde.mxf;6a3c2be7577f31bd
A_0900C003_220927_102240_a1BZ0_hde.mxf;6606cf4d3b1ebc17
A_0900C004_220927_102334_a1BZ0_hde.mxf;cd0a2dca6f8f6c21
A_0900C005_220927_102506_a1BZ0_hde.mxf;e617e05dae72e5a6
A_0900C006_220927_102615_a1BZ0_hde.mxf;d6e487264d1246b0
A_0900C007_220927_102720_a1BZ0_hde.mxf;80f5f5683e1f326d
使用xq
(来自安德烈·基斯柳克),您可以使用以下方式获得正确引用的 CSV 文档:
xq -r '.hashlist.hashes.hash | map([.path."#text",.xxh64."#text"] | @csv)[]' file.xml
或者,
xq -r '.hashlist.hashes.hash[] | [.path."#text",.xxh64."#text"] | @csv' file.xml
如果您想要不带引号的字段;
作为分隔符,您可以在上面的命令中替换@csv
为。join(";")
答案2
问题xmllint
是它对命名空间不友好。
要对具有名称空间的文件执行所需操作,您需要编写:
xmllint --xpath "/*[local-name()='hashlist']/*[local-name()='hashes']/*[local-name()='hash']/*[local-name()='path']/text()" file.xml
或者只是预先从原始文件中删除名称空间。
答案3
您可以使用希德尔和jq:
xidel -s -e "[//path, //xxh64]" < test.xml | jq -r '. | transpose| .[] | @tsv'
(假设你的xml数据在test.xml
)