【问题标题】:Xmlstarlet select nodes and adding subnodesXmlstarlet 选择节点并添加子节点
【发布时间】:2019-09-11 12:53:53
【问题描述】:

我正在尝试自动将新子节点添加到 nexus-core-feature-3.16.1-02.xml 因为我们正在使用一些插件来完成“盒子”解决方案所没有的工作。 要点是,当新版本的nexus-container 发布时,我有一个bash 脚本,它运行新的测试容器版本并将新的default-xml 文件复制到适当的文件夹中。 下一步是编辑此文件并添加一些新功能以使插件工作。当这个完成的旧容器停止时,新的 xml-replace 旧容器,我正在启动一个带有映射的 nexus-data 和 default-xml 的 docker-container。 为了使该插件正常工作,我需要对 default-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>

所以我在谷歌和 SO 有一段时间了,但我仍然卡住了。 比如这个案例: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-online 测试器中检查这一点,并且在测试器内部一切正常。

接下来我在本文中使用更简单的例子: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 文件?更复杂\奇怪的结构?很高兴有任何建议

【问题讨论】:

    标签: xml xmlstarlet


    【解决方案1】:

    为什么相同的方法不适用于 nexus-xml 文件?

    这是因为您的 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>
    

    【讨论】:

    • 感谢 Daniel 的精彩回答!这对我来说似乎是可行的解决方案,但仍然需要为我的情况做一些修改:)
    • @АфанасьевДмитрий - 很高兴我能帮上忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2011-04-22
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    相关资源
    最近更新 更多