【问题标题】:How do I select and edit an xml node with xmlstartlet?如何使用 xmlstartlet 选择和编辑 xml 节点?
【发布时间】:2011-04-08 06:43:55
【问题描述】:

这里我选择节点:

$ xmlstarlet sel -t -c "/configuration/property[name='http.agent.name']"/value conf/nutch-default.xml 
<value/>

这不会编辑它:

$ xmlstarlet edit  "/configuration/property[name='http.agent.name']"/value -v 'test' conf/nutch-default.xml 
I/O warning : failed to load external entity "/configuration/property[name='http.agent.name']/value"

什么是 xmlstartlet 命令会改变更改? xmlstartlet 尚不支持 AFAIK -x。

我正在处理conf/nutch-default.xml

$ xmlstarlet ed --help
XMLStarlet Toolkit: Edit XML document(s)
Usage: xml ed <global-options> {<action>} [ <xml-file-or-uri> ... ]
where
  <global-options>  - global options for editing
  <xml-file-or-uri> - input XML document file name/uri (stdin otherwise)

<global-options> are:
  -P (or --pf)        - preserve original formatting
  -S (or --ps)        - preserve non-significant spaces
  -O (or --omit-decl) - omit XML declaration (<?xml ...?>)
  -N <name>=<value>   - predefine namespaces (name without 'xmlns:')
                        ex: xsql=urn:oracle-xsql
                        Multiple -N options are allowed.
                        -N options must be last global options.
  --help or -h        - display help

where <action>
  -d or --delete <xpath>
  -i or --insert <xpath> -t (--type) elem|text|attr -n <name> -v (--value) <value>
  -a or --append <xpath> -t (--type) elem|text|attr -n <name> -v (--value) <value>
  -s or --subnode <xpath> -t (--type) elem|text|attr -n <name> -v (--value) <value>
  -m or --move <xpath1> <xpath2>
  -r or --rename <xpath1> -v <new-name>
  -u or --update <xpath> -v (--value) <value>
             -x (--expr) <xpath> (-x is not implemented yet)

XMLStarlet is a command line toolkit to query/edit/check/transform
XML documents (for more information see http://xmlstar.sourceforge.net/)

$ xmlstarlet --version
1.0.1

【问题讨论】:

    标签: xml bash command-line-interface


    【解决方案1】:

    您可以将 nutch-default.xml 的全部内容读取到一个变量中,使用 xmlstarlet 编辑该变量的内容,然后将结果再次写回 nutch-default.xml。

    另一种方法是使用Redirect output from sed 's/c/d/' myFile to myFile 中所述的打开文件句柄。

    xmlstarlet --version  # 1.0.6
    xmlstarlet ed --help | less -Ip 'inplace'
    
    # 1.
    # in-place version using xmlstarlet only
    curl -L -s -o nutch-default.xml 'http://svn.apache.org/viewvc/nutch/branches/branch-1.3/conf/nutch-default.xml?view=co&revision=1079746&content-type=text%2Fplain'
    xmlstarlet edit -L -u "/configuration/property[name='http.agent.name']"/value -v 'test' nutch-default.xml
    xmlstarlet sel -t -c "/configuration/property[name='http.agent.name']"/value nutch-default.xml 
    
    
    # 2.
    # variable version
    curl -L -s -o nutch-default.xml 'http://svn.apache.org/viewvc/nutch/branches/branch-1.3/conf/nutch-default.xml?view=co&revision=1079746&content-type=text%2Fplain'
    xmlstr="$(< nutch-default.xml)"   # save file contents to variable
    
    printf '%s\n' "$xmlstr" |
    xmlstarlet edit -u "/configuration/property[name='http.agent.name']"/value -v 'test' > nutch-default.xml
    
    xmlstarlet sel -t -c "/configuration/property[name='http.agent.name']"/value nutch-default.xml 
    
    
    # 3.
    # file handle version
    # cf. https://stackoverflow.com/questions/2585438/redirect-output-from-sed-s-c-d-myfile-to-myfile
    curl -L -s -o nutch-default.xml 'http://svn.apache.org/viewvc/nutch/branches/branch-1.3/conf/nutch-default.xml?view=co&revision=1079746&content-type=text%2Fplain'
    exec 3<nutch-default.xml
    rm nutch-default.xml   # prevent open file from being truncated
    xmlstarlet edit -u "/configuration/property[name='http.agent.name']"/value -v 'test' <&3 >nutch-default.xml
    xmlstarlet sel -t -c "/configuration/property[name='http.agent.name']"/value nutch-default.xml 
    

    【讨论】:

    • 谢谢!我有 $ sudo port upgrade xmlstarlet,现在我设法使用了 -L,它达到了预期。
    【解决方案2】:

    文档非常非常差。我偶然发现了 Stackoverflow 超过一天,在阅读了许多关于堆栈溢出的答案后,我终于为定义了命名空间的元素的值导出了“编辑文件就地选项”的解决方案。给定一个 XML 如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <config>
      <cassandra xmlns="http://venus.com/ns/mibs/VENUS-MODE/1.0">
        <clusterName>test-cluster</clusterName>
        <cassandraUsername>simba</cassandraUsername>
        <cassandraPassword>U2FsdGVkX1/Zc4NAsF59coYZLaCgddJ9b91s016HUbs=</cassandraPassword>
        <cassandraService>Local</cassandraService>
      </cassandra>
      <monit xmlns="http://venus.com/ns/mibs/VENUS-MODE/1.0">
        <cpuUsageThreshold>70</cpuUsageThreshold>
        <cpuUsageThresholdClear>60</cpuUsageThresholdClear>
        <memoryUsageThreshold>70</memoryUsageThreshold>
        <memoryUsageThresholdClear>60</memoryUsageThresholdClear>
      </monit>
    </config>
    

    修改 /config/cassandra/clusterName 元素值的 xmlstarlet 命令将是:

    xmlstarlet ed -L -N x="http://venus.com/ns/mibs/VENUS-MODE/1.0" -u "//config/x:cassandra/x:cassandraPassword" -v "test123" Myfile.xml

    记住 ed & -L 选项必须在 -N(命名空间)选项之前。希望这对寻找命名空间问题的编辑文件就地选项的人有所帮助。

    【讨论】:

      【解决方案3】:

      我的xmlstarlet 版本需要edit 命令的action 选项。如果要使用新值更新节点,则必须指定 -u,例如:

      xmlstarlet edit -u "/configuration/property[name='http.agent.name']"/value -v 'test' conf/nutch-default.xml
      

      【讨论】:

      • @bmk:你是对的!但是现在打印到标准输出,-L 应该修改文件,但显然不在我的版本中。我还能怎么办?使用 > 重定向输出仅清空文件
      • @simpatico:我的xmlstarlet 版本似乎没有任何-L 选项。你能给我完整的命令行吗?然后我会更新我的答案。
      • @bmk:不是我的版本,我指的是stackoverflow.com/questions/1554143/…。我们还能如何使用更新来修改文件?
      • @simpatico:我认为我们必须将命令的输出重定向到一个新的临时文件,然后将其移到原始文件上(xmlstarlet edit -u "/configuration/property[name='http.agent.name']"/value -v 'test' conf/nutch-default.xml &gt; conf/nutch-default.xml.tmp; mv conf/nutch-default.xml.tmp conf/nutch-default.xml)。
      • @bmk:我认为 sed 会更容易使用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      相关资源
      最近更新 更多