การปรับเปลี่ยนบรรทัดคำสั่ง XML (สคริปต์เชลล์)


9

วิธีจัดการ XML จากบรรทัดคำสั่งในเชลล์สคริปต์

มีคำสั่งมากมายสำหรับการจัดการข้อมูลแบบตาราง, ตัวแปรสภาพแวดล้อมการแทนที่หรือแทนที่ส่วนข้อความด้วย regex แต่ฉันไม่พบอะไรเลยสำหรับ XML

บิลด์สคริปต์ของฉันจำเป็นต้องแทรกแท็กที่มีเนื้อหาภายในแท็กหลักของเอกสาร xml และฉันพบว่ามันเป็น overkill ในการติดตั้ง java, perl หรือ python ในระบบปฏิบัติการสำหรับจุดประสงค์นั้น (สคริปต์ของฉันทำใน gitlab ด้วยอิมเมจ docker งานของฉันด้วยเครื่องมือที่มีใน maven: ภาพ 3.5-jdk-8 จะเป็นความฝัน)

ฉันไม่ต้องการที่จะจัดการกับ XML ที่มี 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>

ภายในแท็กโครงการ (และมันก็ไม่สำคัญว่าจะเป็นในตอนเริ่มต้นหรือตอนท้าย


โพสต์อินพุต xml ของคุณและผลลัพธ์ที่คาดหวัง
RomanPerekhrest

ดังนั้นข้อกำหนดเฉพาะสำหรับตัวแยกวิเคราะห์ XML ที่สามารถเรียกใช้จากบรรทัดคำสั่งที่ไม่ได้ใช้ในภาษาสคริปต์หลักใด ๆ แต่เป็นยูทิลิตี้ C หรือ C ++ (หรือคอมไพล์อื่น ๆ ) อิสระ
Kusalananda

@Kisandaanda ฉันได้ระบุว่าฉันกำลังเรียกใช้สลิปภายในคอนเทนเนอร์ของนักเทียบท่าดังนั้นสิ่งที่สำคัญที่สุดสำหรับฉันคือเพิ่มลงในอิมเมจของ Docker ให้น้อยที่สุดเท่าที่จะทำได้
9ilsdx 9rvj 0lo

หากคุณมีรูปภาพที่มี maven และ jdk แล้ว Java ดูเหมือนจะเป็นตัวเลือกที่ดีที่สุดสำหรับฉัน .... ทำไมคุณถึงพิจารณา Java heavyweight ในกรณีนี้
Daniel Pryden

มันอาจคุ้มค่าที่จะถามคำถามนี้เกี่ยวกับ Stack Overflow และการติดแท็กด้วยmaven- ฉันสงสัยว่ามีวิธีที่ดีกว่าในการทำสิ่งที่คุณพยายามทำใน Maven
Daniel Pryden

คำตอบ:


10

XMLStarlet ( http://xmlstar.sourceforge.net/overview.php ) ถูกเขียนใน C และการใช้งานและlibxml2libxslt

รับเอกสาร 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บิตunescapesข้อมูลแทรก (มันจริง unescapes เอกสารทั้งหมดซึ่งอาจจะหรืออาจไม่เป็นปัญหา) และ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: /programming/29298507/xmlstarlet-xinclude-xslt


มันดูน่าสนใจแม้ว่าการแทรกแท็กเดียวมากกว่าหนึ่งครั้ง แต่ไวยากรณ์นั้นค่อนข้างยาว เฉพาะในอูบุนตูเท่านั้นที่มีชื่อว่า 'xmlstarlet' เป็นไปได้หรือไม่ที่จะแทรกเนื้อหาของไฟล์อื่นเป็นแท็กสมมติว่าเนื้อหานั้นเป็น xml ที่ถูกต้อง?
9ilsdx 9rvj 0lo

@ 9ilsdx9rvj0lo ดูคำตอบที่อัปเดต
Kusalananda

"จริง ๆ แล้วมัน unescapes เอกสารทั้งหมดซึ่งอาจหรืออาจไม่ใช่ปัญหา" ใช่ปัญหาใหญ่แล้ว & amp; ไม่มีการเข้ารหัสทำให้ XML ไม่ถูกต้องอีกต่อไป :(
ปล้น

1

ฉันคิดว่ามันเป็น overkill ในการติดตั้ง java, perl หรือ python ใน OS เพื่อจุดประสงค์นั้น (สคริปต์ของฉันทำใน gitlab ด้วยภาพ docker ดังนั้นการทำงานด้วยเครื่องมือที่มีให้ใน maven: ภาพ 3.5-jdk-8 จะเป็นความฝัน)

มันอาจจะยังเกินกำลัง แต่ถ้าคุณกังวลกับขนาดของคอนเทนเนอร์คุณสามารถใช้ภาษาที่มีน้ำหนักเบามากเช่น Lua หรือ Guile

จากเอกสาร Lua:

การเพิ่ม Lua ไปยังแอปพลิเคชันไม่ได้เป็นการขยาย tarball สำหรับ Lua 5.3.4 ซึ่งมีซอร์สโค้ดและเอกสารประกอบใช้เวลาบีบอัด 297K และไม่บีบอัด 1.1M แหล่งที่มาประกอบด้วย C. ประมาณ 24000 บรรทัดภายใต้ Linux 64 บิตล่าม Lua ที่สร้างด้วยไลบรามาตรฐาน Lua ทั้งหมดใช้เวลา 246K และไลบรารี่ Lua ใช้เวลา 421K


มันมีมูลค่าการพิจารณาเพียงแค่เพิ่ม LUA ลงในภาชนะบรรจุที่ต้องขอบคุณสำหรับคำแนะนำ
9ilsdx 9rvj 0lo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.