XML 명령 줄 (쉘 스크립트) 조작


9

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

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

내 빌드 스크립트는 xml 문서의 기본 태그 내에 내용이 포함 된 태그를 삽입해야하며 OS에 Java, perl 또는 python을 설치하기 위해 과도한 노력을 기울입니다 (스크립트는 docker 이미지가있는 gitlab에서 수행되므로 maven : 3.5-jdk-8 이미지로 제공되는 도구를 사용한 제 직업은 꿈일 것입니다).

내 빌드 스크립트에서는 그것이 악하기 때문에 작동하지만 sed로 XML을 조작하고 싶지 않습니다 .

예 : 다음 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>

프로젝트 태그 내부 (그리고 시작 또는 끝에 있는지 여부는 중요하지 않습니다.


입력 XML 및 예상 출력 게시
RomanPerekhrest

따라서 특정 요구 사항은 주요 스크립팅 언어로 구현되지 않은 독립형 C 또는 C ++ (또는 기타 컴파일 된) 유틸리티로 명령 줄에서 호출 할 수있는 XML 파서에 대한 것입니까?
Kusalananda

@Kusalanda 나는 docker 컨테이너 내에서 scipts를 실행 중이라고 지정 했으므로 가능한 한 docker 이미지에 조금만 추가하는 것이 가장 중요합니다.
9ilsdx 9rvj 0lo

maven과 jdk가있는 이미지가 있다면 Java가 가장 좋은 옵션처럼 들립니다 .... 왜이 경우 Java 헤비급을 고려합니까?
Daniel Pryden

스택 오버플로와 태그 지정에 대해이 질문을 maven하는 것이 좋습니다 .Maven 자체에서 수행하려는 작업을 수행하는 더 좋은 방법이 있다고 생각합니다.
Daniel Pryden

답변:


10

XMLStarlet는 ( 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 : //.com/questions/29298507/xmlstarlet-xinclude-xslt


하나 이상의 태그를 삽입하는 경우 구문이 상당히 길지만 흥미로워 보입니다. 우분투에서만 이름이 'xmlstarlet'입니다. 내용이 유효한 XML이라고 가정하고 다른 파일의 내용을 태그로 삽입 할 수 있습니까?
9ilsdx 9rvj 0lo

@ 9ilsdx9rvj0lo 업데이트 된 답변보기
Kusalananda

"실제로 문서 전체를 이스케이프 처리하므로 문제가 될 수도 있고 아닐 수도 있습니다." 그래도 거대한 문제, 모든 기존의 & amp; 인코딩되지 않아 XML이 더 이상 유효하지 않습니다. (
rob

1

그 목적으로 OS에 java, perl 또는 python을 설치하는 것이 과도하다는 것을 알았습니다 (제 스크립트는 docker 이미지와 함께 gitlab에서 수행되므로 maven : 3.5-jdk-8 이미지에서 사용할 수있는 도구로 작업을 수행하는 것은 꿈입니다).

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

루아 문서에서 :

응용 프로그램에 Lua를 추가해도 문제가 해결되지 않습니다. 소스 코드와 문서가 포함 된 Lua 5.3.4 용 tarball은 297K 압축 및 1.1M 비 압축을 사용합니다. 이 소스에는 약 24000 줄의 C가 포함되어 있습니다. 64 비트 Linux에서 모든 표준 Lua 라이브러리로 구축 된 Lua 인터프리터는 246K를, Lua 라이브러리는 421K를 사용합니다.


팁 덕분에 LUA를 maven 컨테이너에 추가하는 것을 고려해 볼 가치가 있습니다.
9ilsdx 9rvj 0lo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.