XML 명령줄(셸 스크립트) 작업

XML 명령줄(셸 스크립트) 작업

쉘 스크립트의 명령줄에서 XML을 조작하는 방법은 무엇입니까?

표 형식의 데이터를 조작하거나, 환경 변수를 바꾸거나, 텍스트 조각을 정규식으로 바꾸는 명령은 많이 있지만 XML에 대한 명령은 찾지 못했습니다.

내 빌드 스크립트는 xml 문서의 기본 태그에 콘텐츠가 포함된 태그를 삽입해야 하며, 이 목적을 위해 운영 체제에 java, perl 또는 python을 설치하는 것은 과잉이라는 것을 알았습니다(내 스크립트는 gitlab docker 이미지에서 사용되므로 maven:3.5-jdk-8 이미지에 있는 도구를 사용하여 내가 하는 일을 하는 것이 꿈일 것입니다.

나는 XML을 조작하기 위해 sed를 사용하고 싶지 않습니다. 하지만 내 빌드 스크립트에서는 sed가 작동하기 때문에 작동합니다.사악한.

예: 다음 XML이 있습니다.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>  
  <!-- a lot of other tags-->
</project>  

다음 블록을 삽입하고 싶습니다.

<distributionManagement>
    <repository>
        <id>private-releases</id>
        <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
</distributionManagement>

프로젝트 태그 내부(시작 부분인지 끝 부분인지는 전혀 중요하지 않습니다.

답변1

XML별표(http://xmlstar.sourceforge.net/overview.php)은 C로 작성되었으며 libxml2및 를 사용합니다 libxslt.

XML 문서가 주어지면

<?xml version="1.0"?>
<root>
  <tag>data</tag>
</root>

root다음을 사용하여 하위 노드를 삽입할 수 있습니다.

xml ed -s '/root' -t elem -n 'newtag' -v 'newdata' file.xml

생산하다

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>newdata</newtag>
</root>

file.xml많은 내용을 삽입하세요(여기서는 맨 위의 원본 콘텐츠를 사용함).

xml ed -s '/root' -t elem -n 'newtag' \
       -s '/root/newtag' -t elem -n 'subtag' -v 'subdata' file.xml

이것은 생산할 것입니다

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>
    <subtag>subdata</subtag>
  </newtag>
</root>

질문의 예를 들면 다음과 같습니다.

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -s '/x:project/distributionManagement' -t elem -n 'repository' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'id' \
         -v 'private-releases' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'url' \
         -v 'https://my.private.server.com/nexus/repository/maven-releases/' \
    file.xml

결과:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

이전에 준비한 XML 파일을 XML 어딘가에 삽입합니다.

질문의 원본 XML이 있고 file.xml새 노드에 포함되어야 하는 추가 비트가 distributinManagement있다고 가정합니다 new.xml(그러나아니요노드 레이블 자체),다음을 수행할 수 있습니다.new.xml루트 노드 삽입 :

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -v "$(<new.xml)" file.xml | xml unesc | xml fo

<XMLStarlet은 문자 와 같이 이스케이프해야 하는 데이터를 자동으로 이스케이프합니다 >. 그 xml unesc비트탈출하다삽입된 데이터(실제로 전체 문서를 이스케이프하며 이는 문제가 될 수도 있고 아닐 수도 있음)와 xml fo결과 XML 문서의 형식이 다시 지정됩니다.

밝혀지다

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

나는 그것을 하는 것에 대해 약간 긴장했지만 "하지만 효과가 있다".

StackOverflow에 대한 관련 질문도 참조하세요.https://stackoverflow.com/questions/29298507/xmlstarlet-xinclude-xslt

답변2

이 목적을 위해 운영 체제에 Java, Perl 또는 Python을 설치하는 것은 과잉이라는 것을 알았습니다. (내 스크립트는 docker 이미지를 사용하여 gitlab에서 수행되었으므로 maven:3.5-jdk-8 이미지에 제공된 도구를 사용하여 작업을 수행했습니다. 꿈이 되세요).

여전히 과잉일 수도 있지만 컨테이너 크기에만 관심이 있다면 Lua 또는 Guile과 같은 매우 가벼운 언어를 사용할 수 있습니다.

Lua 문서에서:

애플리케이션에 Lua를 추가한다고 해서 애플리케이션이 커지지는 않습니다. Lua 5.3.4 타르볼에는 소스 코드와 문서가 포함되어 있으며 압축률은 297K이고 압축되지 않은 크기는 1.1M입니다. 소스 코드에는 약 24,000줄의 C 코드가 포함되어 있습니다. 64비트 Linux에서 모든 표준 Lua 라이브러리로 구축된 Lua 인터프리터에는 246K가 필요하고 Lua 라이브러리에는 421K가 필요합니다.

관련 정보