9il*_*0lo 9 xml shell-script docker
如何在 shell 脚本中从命令行操作 XML?
有很多用于操作表格数据、替换环境变量或用正则表达式替换文本片段的命令,但我没有找到任何适用于 XML 的命令。
我的构建脚本需要在 xml 文档的主标签中插入一个带有内容的标签,我发现为此目的在 OS 中安装 java、perl 或 python 是一种矫枉过正(我的脚本是在带有 docker 图像的 gitlab 中完成的,所以这样做我使用 maven:3.5-jdk-8 图像中可用工具的工作将是一个梦想)。
我不想用 sed 操作 XML,尽管在我的构建脚本中它可以工作,因为它是evil。
示例:我有以下 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>
Run Code Online (Sandbox Code Playgroud)
我想插入以下块:
<distributionManagement>
<repository>
<id>private-releases</id>
<url>https://my.private.server.com/nexus/repository/maven-releases/</url>
</repository>
</distributionManagement>
Run Code Online (Sandbox Code Playgroud)
在项目标签内(并且它是在开头还是结尾完全无关紧要。
Kus*_*nda 10
XMLStarlet ( http://xmlstar.sourceforge.net/overview.php ) 是用 C 编写的,使用libxml2和libxslt。
给定 XML 文档
<?xml version="1.0"?>
<root>
<tag>data</tag>
</root>
Run Code Online (Sandbox Code Playgroud)
root可以使用插入子节点
xml ed -s '/root' -t elem -n 'newtag' -v 'newdata' file.xml
Run Code Online (Sandbox Code Playgroud)
产生
<?xml version="1.0"?>
<root>
<tag>data</tag>
<newtag>newdata</newtag>
</root>
Run Code Online (Sandbox Code Playgroud)
插入很多东西(使用file.xml此处顶部的原始内容):
xml ed -s '/root' -t elem -n 'newtag' \
-s '/root/newtag' -t elem -n 'subtag' -v 'subdata' file.xml
Run Code Online (Sandbox Code Playgroud)
这产生
<?xml version="1.0"?>
<root>
<tag>data</tag>
<newtag>
<subtag>subdata</subtag>
</newtag>
</root>
Run Code Online (Sandbox Code Playgroud)
对于问题中的示例:
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
Run Code Online (Sandbox Code Playgroud)
结果:
<?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>
Run Code Online (Sandbox Code Playgroud)
在 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
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
我对这样做有点不安,“但它有效”。
另请参阅 StackOverflow 上的这个相关问题:https ://stackoverflow.com/questions/29298507/xmlstarlet-xinclude-xslt