Xmlstarlet select 节点和添加子节点
Xmlstarlet select nodes and adding subnodes
我正在尝试自动将新子节点添加到 nexus-core-feature-3.16.1-02.xml 因为我们正在使用一些 "box" 解决方案未提供的插件。
要点是,当新版本的 nexus-container 发布时,我有一个 bash-script 运行新的测试容器版本并将新的 default-xml 文件复制到适当的文件夹。
下一步是编辑此文件并添加一些新功能以使插件工作。当这个完成的旧容器停止时,新的 xml-替换旧的,我正在启动一个 docker-具有映射的关系数据和默认值-xml 的容器。
为了使该插件正常工作,我需要对默认的 xml 文件添加一些更改。我想为此使用 xmlstarlet。
将此添加到 "nexus-core-feature" 部分:
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
到文件末尾xml-file
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>
所以我 google 有一段时间了,但我仍然卡住了。
例如这种情况:How to insert a new element under another with xmlstarlet?
做类似的事情似乎很简单,我试过这个:
xmlstarlet ed -s /features/feature/feature -t elem -n featureTMP -v "nexus-apt-repositroy" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP P -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
我怀疑我的错误曾经(现在)在节点路径中。
下一步是检查节点
xmlstarlet sel -t -c "/" nexus-core-feature-3.16.1-02-features.xml
输出是整个 xml 文件,看起来没问题
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
...
但是当我尝试进入节点时,结果总是空的:
xmlstarlet sel -t -c "/features" nexus-core-feature-3.16.1-02-features.xml
使用属性选择器它仍然是空的:
xmlstarlet sel -t -c "/features/feature[@name="nexus-core-feature"]" nexus-core-feature-3.16.1-02-features.xml
尝试在 XPath 在线测试器和测试器内部检查一切正常。
接下来我在本文中使用更简单的示例:https://unix.stackexchange.com/questions/386965/insert-custom-xml-tag-into-a-xml-file-in-a-bash-script
并尝试浏览 arctilce 中的示例文件,它似乎没问题。
xmlstarlet sel -t -c "/server-groups" file.xml
输出:
<server-groups>
<server-group name="main-server-group" profile="full">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<jvm-options>
<option value="somevalue"/>
</jvm-options>
</jvm>
<socket-binding-group ref="full-sockets"/>
</server-group>
</server-groups>
下一步
xmlstarlet sel -t -c "/server-groups/server-group/jvm" file.xml
输出:
<jvm name="default">
<heap size="64m" max-size="512m"/>
<jvm-options>
<option value="somevalue"/>
</jvm-options>
</jvm>
这让我很困惑...为什么同样的方法不适用于 nexus-xml 文件?更多 complex\strange 结构?很高兴收到任何建议
Why the same approach doesn't work with nexus-xml file?
这是因为您的 nexus XML 文件位于默认命名空间 (http://karaf.apache.org/xmlns/features/v1.4.0
) 中。
如果您使用的是 xmlstarlet 1.0.5 或更高版本,您可以在 XPath 中使用 _:
来匹配任何命名空间。否则,您必须将名称空间绑定到带有 -N
的前缀。 See here 获取更多信息。
这是您第一次尝试的更新示例:
xmlstarlet ed -s /_:features/_:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
这是使用 -N
...
的替代方法
xmlstarlet ed -N f="http://karaf.apache.org/xmlns/features/v1.4.0" -s /f:features/f:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
这两个都会产生以下输出:
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
</features>
可以用相同的方式添加第二个 feature
,但您也可以通过在带有 tr command 的 xmlstarlet 中使用 XSLT 来简化整个过程。 (无论如何,我认为它更简单。)
XSLT (test.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://karaf.apache.org/xmlns/features/v1.4.0"
xmlns="http://karaf.apache.org/xmlns/features/v1.4.0"
exclude-result-prefixes="f">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="f:features">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</xsl:copy>
</xsl:template>
<xsl:template match="f:feature[@name='nexus-core-feature']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
xmlstarlet 命令
xmlstarlet tr test.xsl nexus-core-feature-3.16.1-02-features.xml
输出
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>
我正在尝试自动将新子节点添加到 nexus-core-feature-3.16.1-02.xml 因为我们正在使用一些 "box" 解决方案未提供的插件。 要点是,当新版本的 nexus-container 发布时,我有一个 bash-script 运行新的测试容器版本并将新的 default-xml 文件复制到适当的文件夹。 下一步是编辑此文件并添加一些新功能以使插件工作。当这个完成的旧容器停止时,新的 xml-替换旧的,我正在启动一个 docker-具有映射的关系数据和默认值-xml 的容器。 为了使该插件正常工作,我需要对默认的 xml 文件添加一些更改。我想为此使用 xmlstarlet。 将此添加到 "nexus-core-feature" 部分:
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
到文件末尾xml-file
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>
所以我 google 有一段时间了,但我仍然卡住了。 例如这种情况:How to insert a new element under another with xmlstarlet?
做类似的事情似乎很简单,我试过这个:
xmlstarlet ed -s /features/feature/feature -t elem -n featureTMP -v "nexus-apt-repositroy" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP P -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
我怀疑我的错误曾经(现在)在节点路径中。
下一步是检查节点
xmlstarlet sel -t -c "/" nexus-core-feature-3.16.1-02-features.xml
输出是整个 xml 文件,看起来没问题
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
...
但是当我尝试进入节点时,结果总是空的:
xmlstarlet sel -t -c "/features" nexus-core-feature-3.16.1-02-features.xml
使用属性选择器它仍然是空的:
xmlstarlet sel -t -c "/features/feature[@name="nexus-core-feature"]" nexus-core-feature-3.16.1-02-features.xml
尝试在 XPath 在线测试器和测试器内部检查一切正常。
接下来我在本文中使用更简单的示例:https://unix.stackexchange.com/questions/386965/insert-custom-xml-tag-into-a-xml-file-in-a-bash-script
并尝试浏览 arctilce 中的示例文件,它似乎没问题。
xmlstarlet sel -t -c "/server-groups" file.xml
输出:
<server-groups>
<server-group name="main-server-group" profile="full">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<jvm-options>
<option value="somevalue"/>
</jvm-options>
</jvm>
<socket-binding-group ref="full-sockets"/>
</server-group>
</server-groups>
下一步
xmlstarlet sel -t -c "/server-groups/server-group/jvm" file.xml
输出:
<jvm name="default">
<heap size="64m" max-size="512m"/>
<jvm-options>
<option value="somevalue"/>
</jvm-options>
</jvm>
这让我很困惑...为什么同样的方法不适用于 nexus-xml 文件?更多 complex\strange 结构?很高兴收到任何建议
Why the same approach doesn't work with nexus-xml file?
这是因为您的 nexus XML 文件位于默认命名空间 (http://karaf.apache.org/xmlns/features/v1.4.0
) 中。
如果您使用的是 xmlstarlet 1.0.5 或更高版本,您可以在 XPath 中使用 _:
来匹配任何命名空间。否则,您必须将名称空间绑定到带有 -N
的前缀。 See here 获取更多信息。
这是您第一次尝试的更新示例:
xmlstarlet ed -s /_:features/_:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
这是使用 -N
...
xmlstarlet ed -N f="http://karaf.apache.org/xmlns/features/v1.4.0" -s /f:features/f:feature -t elem -n featureTMP -v "nexus-repository-apt" \
-i //featureTMP -t attr -n "version" -v "1.0.9" \
-i //featureTMP -t attr -n "prerequisite" -v "false" \
-i //featureTMP -t attr -n "dependency" -v "false" \
-r //featureTMP -v feature nexus-core-feature-3.16.1-02-features.xml
这两个都会产生以下输出:
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
</features>
可以用相同的方式添加第二个 feature
,但您也可以通过在带有 tr command 的 xmlstarlet 中使用 XSLT 来简化整个过程。 (无论如何,我认为它更简单。)
XSLT (test.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://karaf.apache.org/xmlns/features/v1.4.0"
xmlns="http://karaf.apache.org/xmlns/features/v1.4.0"
exclude-result-prefixes="f">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="f:features">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</xsl:copy>
</xsl:template>
<xsl:template match="f:feature[@name='nexus-core-feature']">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
xmlstarlet 命令
xmlstarlet tr test.xsl nexus-core-feature-3.16.1-02-features.xml
输出
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="nexus-core-feature">
<feature name="nexus-core-feature" description="org.sonatype.nexus.assemblies:nexus-core-feature" version="3.16.1.02">
<details>org.sonatype.nexus.assemblies:nexus-core-feature</details>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-audit-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-blobstore-tasks</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-ssl-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-coreui-plugin</feature>
<feature version="3.16.1.02" prerequisite="false" dependency="false">nexus-repository-httpbridge</feature>
<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
</feature>
<feature name="nexus-repository-apt" description="net.staticsnow:nexus-repository-apt" version="1.0.10">
<details>net.staticsnow:nexus-repository-apt</details>
<bundle>mvn:net.staticsnow/nexus-repository-apt/1.0.10</bundle>
<bundle>mvn:org.apache.commons/commons-compress/1.18</bundle>
<bundle>mvn:org.tukaani/xz/1.8</bundle>
</feature>
</features>