XML 파일에서 CSV 만들기

XML 파일에서 CSV 만들기

XML의 일부 정보만 포함된 XML에서 CSV를 만들려고 합니다.

이것은 내 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

등...

나는 노력했다

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을 추가하여 출력합니다(뒤에 줄 바꿈).pathxxh64;

문서는 암시적 네임스페이스를 사용하므로 문서 루트 요소의 네임스페이스를 사용하여 명시적인 네임스페이스 접두사를 선언한 다음 이를 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

따옴표 없이 필드를 구분 기호로 사용하려면 위 명령에서 로 ;바꿀 수 있습니다 .@csvjoin(";")

답변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)

관련 정보