12,000개 이상의 XML 파일을 구문 분석했습니다.

12,000개 이상의 XML 파일을 구문 분석했습니다.

12,000개 이상의 XML 파일이 포함된 폴더가 있습니다. 이 폴더에서 특정 기준을 충족하는 파일 목록을 가져와야 합니다.

XML 파일에는 이라는 노드가 있습니다 /BillingData/InvoiceLinesList/InvoiceLines. InvoiceLines하나 이상이 있을 수 있습니다 InvoiceLinesList. 에서 값이 인 InvoiceLines태그를 검색해야 하며 <charge>, 이름이 지정된 동일한 99태그 내에 값이 인 태그가 있습니다.InvoiceLines<chargeType>D

가장 좋은 접근 방식은 무엇입니까? 를 사용하면 awk이런게 가능할지도 모른다고 생각했는데, 잘 못해서 여러 기준으로 검색하는 방법을 못 찾겠어요 awk. 여기서 잠재적인 접근 방식을 볼 수 있지만 xmlstarlet여러 태그에서 별도의 값을 찾는 것이 아니라 단일 태그에서 하나 또는 다른 값만 찾습니다.

답변1

일반적으로 XML(및 JSON 및 YAML 등과 같은 기타 유사한 형식) awk을 구문 분석하는 데 적합하지 않습니다. sed예를 들어, 이 XML 예제에서는 노드가 저장되는 순서 InvoiceLines나 줄 바꿈으로 구분되는지 여부를 알 수 없습니다. XML 형식은 이러한 사항에 신경 쓰지 않지만 가능한 모든 경우(데이터의 가능한 모든 인코딩 포함)를 다루기 위해 특별한 주의를 기울이지 않는 한 awkOR 스크립트는 쉽게 실패할 수 있습니다. sed어떤 장치에 관계없이 구문 분석됩니다.

따라서 XML 파서(예: 내장 파서 xmlstarlet)를 사용하는 것이 올바른 접근 방식입니다.


다음 명령은 파일에서 하나 이상의 필수 노드가 발견되면 입력 파일의 파일 이름을 인쇄합니다 file.xml. 여러 InvoiceLines노드가 일치하면 파일 이름은 사이에 줄 바꿈을 포함하여 여러 번 인쇄됩니다. 이는 처음부터 개행 문자가 포함된 파일 이름을 억제한다는 의미입니다.

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl file.xml

XPATH 쿼리는 지정된 값을 가진 InvoiceLines하위 노드가 있는 모든 노드 와 일치합니다. 하나에 대해 테스트하는 대신 사용chargeTypecharge@chargechargecharge 속성InvoiceLines그건 그렇고, 노드에서.

단일 디렉터리의 모든 XML 파일에 이를 적용합니다.

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl ./*.xml

파일이 너무 많아 위에서 오류가 발생하는 경우 다음을 사용할 수 있습니다 xargs.

printf '%s\n' ./*.xml | xargs xmlstarlet -t -m ...

또는 find(하위 디렉토리도 검색합니다):

find . -type f -name '*.xml' -exec xmlstarlet -t -m ... {} +

uniq파일 목록을 고유하게 만들려면 결과를 파이프하십시오.


위의 내용을 테스트하기 위해 다음 XML을 사용했습니다.

<BillingData>
    <InvoiceLinesList>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>E</chargeType>
            <charge>99</charge>
        </InvoiceLines>
    </InvoiceLinesList>
</BillingData>

관련 정보