Thao tác dòng lệnh XML (shell script)


9

Làm cách nào để thao tác XML từ dòng lệnh trong shell script?

Có nhiều lệnh để thao tác dữ liệu dạng bảng, thay thế biến môi trường hoặc thay thế các đoạn văn bản bằng regex, nhưng tôi không tìm thấy gì cho XML.

Tập lệnh xây dựng của tôi cần chèn một thẻ có nội dung trong thẻ chính của tài liệu xml và tôi thấy nó quá mức cần thiết để cài đặt java, perl hoặc python trong HĐH cho mục đích đó (tập lệnh của tôi được thực hiện trong gitlab với hình ảnh docker, vì vậy công việc của tôi với các công cụ có sẵn trong maven: hình ảnh 3,5-jdk-8 sẽ là một giấc mơ).

Tôi không muốn thao túng XML bằng sed, mặc dù trong kịch bản xây dựng của tôi, nó sẽ hoạt động, vì nó xấu .

Ví dụ: Tôi có xml sau:

<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>  

Và tôi muốn chèn khối sau:

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

bên trong thẻ dự án (và nó hoàn toàn không thành vấn đề nếu nó sẽ ở đầu hoặc cuối.


đăng xml đầu vào của bạn và đầu ra dự kiến
RomanPerekhrest

Vì vậy, các yêu cầu cụ thể là dành cho trình phân tích cú pháp XML có thể được gọi từ dòng lệnh không được triển khai trong bất kỳ ngôn ngữ kịch bản chính nào, nhưng tiện ích C hoặc C ++ (hoặc được biên dịch) khác?
Kusalananda

@Kusalanda Tôi đã chỉ định Tôi đang chạy scipts trong các container docker, vì vậy điều quan trọng nhất đối với tôi là thêm ít nhất vào hình ảnh docker càng tốt.
9ilsdx 9rvj 0lo

Nếu bạn có một hình ảnh với maven và jdk thì Java có vẻ như là lựa chọn tốt nhất đối với tôi .... tại sao bạn lại coi Java nặng trong trường hợp này?
Daniel Pryden

Có lẽ đáng để đặt câu hỏi này trên Stack Overflow và gắn thẻ maven- Tôi nghi ngờ có cách tốt hơn để làm những gì bạn đang cố gắng thực hiện trong chính Maven.
Daniel Pryden

Câu trả lời:


10

XMLStarlet ( http://xmlstar.sourceforge.net/overview.php ) được viết bằng C và sử dụng libxml2libxslt.

Đưa ra tài liệu XML

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

một mã con rootcó thể được chèn bằng cách sử dụng

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

sản xuất

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

Chèn nhiều thứ (sử dụng bản gốc file.xmlở trên cùng ở đây):

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

Điều này tạo ra

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

Ví dụ trong câu hỏi:

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

Kết quả:

<?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>

Chèn một tệp XML đã chuẩn bị trước đó tại một vị trí trong XML:

Giả sử XML gốc từ câu hỏi được đặt vào file.xmlvà các bit bổ sung sẽ có trong distributinManagementnút mới nằm trong new.xml(chứ không phải chính thẻ nút), người ta có thể thực hiện các thao tác sau để chèn new.xmlvào nút gốc:

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 sẽ tự động thoát dữ liệu cần thoát, chẳng hạn như <và các >ký tự. Các xml unescchút unescapes dữ liệu chèn (nó thực sự unescapes toàn bộ tài liệu, mà có thể hoặc không thể là một vấn đề), và xml fođịnh dạng lại kết quả tài liệu XML.

Kết quả là

<?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>

Tôi hơi khó chịu khi làm theo cách này, "nhưng nó hoạt động".

Xem thêm câu hỏi liên quan này trên StackOverflow: /programming/29298507/xmlstarlet-xinclude-xslt


Có vẻ thú vị, mặc dù để chèn nhiều hơn một thẻ, cú pháp khá dài. Chỉ có điều trong Ubuntu, nó được đặt tên là 'xmlstarlet'. Có thể chèn nội dung của tệp khác dưới dạng thẻ, giả sử rằng nội dung đó là xml hợp lệ?
9ilsdx 9rvj 0lo

@ 9ilsdx9rvj0lo Xem câu trả lời cập nhật.
Kusalananda

"Nó thực sự bỏ qua toàn bộ tài liệu, có thể có hoặc không có vấn đề". Đúng vấn đề lớn, tất cả các & amp; đã không được mã hóa khiến XML không còn hiệu lực :(
cướp

1

Tôi thấy việc cài đặt java, perl hoặc python trong HĐH cho mục đích đó là quá mức cần thiết

nó có thể vẫn còn quá mức cần thiết, nhưng nếu bạn chỉ quan tâm đến kích thước của thùng chứa, bạn có thể sử dụng một ngôn ngữ rất nhẹ như Lua hoặc Guile.

từ các tài liệu Lua:

Thêm Lua vào một ứng dụng không làm phình nó. Tarball cho Lua 5.3.4, chứa mã nguồn và tài liệu, mất 297K nén và 1.1M không nén. Nguồn chứa khoảng 24000 dòng C. Trong Linux 64 bit, trình thông dịch Lua được xây dựng với tất cả các thư viện Lua tiêu chuẩn mất 246K và thư viện Lua mất 421K.


Thật đáng để xem xét chỉ đơn giản là thêm LUA vào thùng chứa maven, cảm ơn vì tiền boa.
9ilsdx 9rvj 0lo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.