Xmlstarlet 选择节点并添加子节点

3

我正在尝试自动添加新的子节点到nexus-core-feature-3.16.1-02.xml文件中。因为我们在工作中使用了一些插件,这些插件并没有随着“盒式”解决方案一起提供。

重点在于,当nexus-container发布新版本时,我有一个bash脚本来运行新的test-container版本,并将新的默认xml文件复制到适当的文件夹中。接下来的步骤是编辑这个文件,并添加一些新功能,使插件能够正常工作。完成后,旧容器停止,新的xml替换旧的文件,然后我启动一个带有映射nexus-data和默认xml的docker容器。

为了确保这个插件正常工作,我需要向默认xml文件中添加一些更改。我想使用xmlstarlet完成这个任务。

将以下内容添加到“nexus-core-feature”部分:

<feature version="1.0.9" prerequisite="false" dependency="false">nexus-repository-apt</feature>
  </feature>

将此代码添加到xml文件的末尾

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

我在谷歌和Stack Overflow上搜索了一段时间,但仍然卡住了。

例如这个案例:如何使用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,并尝试浏览文章中的示例文件,似乎没有问题。
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文件?结构更加复杂/奇怪?欢迎任何建议。

1个回答

4

为什么同样的方法不能用在nexus-xml文件上?

这是因为你的nexus XML文件处于默认命名空间 (http://karaf.apache.org/xmlns/features/v1.4.0)。

如果你使用的是xmlstarlet 1.0.5或更高版本,你可以在XPath中使用_:来匹配任何命名空间。否则,你需要使用-N将命名空间绑定到前缀。点击此处了解更多信息。

这是你第一次尝试的更新示例:

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>

您可以以相同的方式添加第二个功能,但是您也可以使用xmlstarlet中的XSLT和tr命令来简化整个过程。(在我看来,这样更简单。)

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

感谢您的出色回答,丹尼尔!对我来说,这似乎是可行的解决方案,但仍需要根据我的情况进行一些修改 :) - Dmitry Afanasyev
@АфанасьевДмитрий - 很高兴我能帮到你! - Daniel Haley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接