首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用xmlstarlet在另一个元素下插入新元素?

如何使用xmlstarlet在另一个元素下插入新元素?
EN

Stack Overflow用户
提问于 2011-05-11 01:47:32
回答 6查看 24.2K关注 0票数 35
代码语言:javascript
复制
$ vim test.xml

<?xml version="1.0" encoding="UTF-8" ?>
<config>
</config>
$ xmlstarlet ed -i "/config" -t elem -n "sub" -v "" test.xml
<?xml version="1.0" encoding="UTF-8"?>
<sub></sub>
<config>
</config>

但我想让sub成为config的孩子。如何更改xpath parameter of -i

额外的好处:是否可以直接插入带有属性的子代,甚至将其设置为一个值?类似于:

代码语言:javascript
复制
$ xmlstarlet ed -i "/config" -t elem -n "sub" -v ""  -a attr -n "class" -v "com.foo" test.xml
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-05-11 23:07:20

使用-s (或--subnode)代替-i。关于额外的好处,你不能直接插入带有属性的元素,但是因为每个编辑操作都是按顺序执行的,所以插入一个元素,然后添加一个属性:

代码语言:javascript
复制
> xml ed -s /config -t elem -n sub -v "" -i /config/sub -t attr -n class -v com.foo test.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<sub class="com.foo"></sub></config>
票数 27
EN

Stack Overflow用户

发布于 2012-02-07 16:02:20

我遇到了一个类似的问题:我有一个Tomcat配置文件(server.xml),并且必须将一个带有预定义属性的<Resource>标记插入到<GlobalNamingResources>部分。

下面是它以前的样子:

代码语言:javascript
复制
<GlobalNamingResources>
    <!-- Editable user database that can also be used
         by UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase"
              auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>

以下是我想要实现的目标:

代码语言:javascript
复制
<GlobalNamingResources>
    <!-- Editable user database that can also be used
         by UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase"
              auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
    <Resource name="jdbc/templateassets"
              auth="Container"
              type="javax.sql.DataSource"
              driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://DBHOST:DBPORT/DBNAME?createDatabaseIfNotExist=false&amp;useUnicode=true&amp;characterEncoding=utf-8"
              username="DBUSER"
              password="DBPASS"
              maxActive="150"
              maxIdle="10"
              initialSize="10"
              validationQuery="SELECT 1"
              testOnBorrow="true" />
</GlobalNamingResources>

下面是我是如何做到这一点的(来自shell脚本的代码片段):

代码语言:javascript
复制
if [ -n "$(xmlstarlet sel -T -t -v "/Server/GlobalNamingResources/Resource[@name='jdbc/templateassets']/@name" server.xml)" ]; then
  echo "Resource jdbc/templateassets already defined in server.xml"
else
  echo "Adding resource jdbc/templateassets to <GlobalNamingResources> in server.xml"
  xmlstarlet ed -P -S -L -s /Server/GlobalNamingResources -t elem -n ResourceTMP -v "" \
    -i //ResourceTMP -t attr -n "name" -v "jdbc/templateassets" \
    -i //ResourceTMP -t attr -n "auth" -v "Container" \
    -i //ResourceTMP -t attr -n "type" -v "javax.sql.DataSource" \
    -i //ResourceTMP -t attr -n "driverClassName" -v "com.mysql.jdbc.Driver" \
    -i //ResourceTMP -t attr -n "url" -v "jdbc:mysql://DBHOST:DBPORT/DBNAME?createDatabaseIfNotExist=false&useUnicode=true&characterEncoding=utf-8" \
    -i //ResourceTMP -t attr -n "username" -v "DBUSER" \
    -i //ResourceTMP -t attr -n "password" -v "DBPASS" \
    -i //ResourceTMP -t attr -n "maxActive" -v "150" \
    -i //ResourceTMP -t attr -n "maxIdle" -v "10" \
    -i //ResourceTMP -t attr -n "initialSize" -v "10" \
    -i //ResourceTMP -t attr -n "validationQuery" -v "SELECT 1" \
    -i //ResourceTMP -t attr -n "testOnBorrow" -v "true" \
    -r //ResourceTMP -v Resource \
    server.xml
fi

诀窍是为新元素临时提供一个惟一的名称,这样以后就可以使用XPATH表达式找到它。添加完所有属性后,名称将改回资源(使用-r)。

其他xmlstarlet选项的含义:

代码语言:javascript
复制
-P (or --pf)        - preserve original formatting
-S (or --ps)        - preserve non-significant spaces
-L (or --inplace)   - edit file inplace
票数 43
EN

Stack Overflow用户

发布于 2015-04-30 12:25:52

从XMLStarlet的1.4.0版(日期为2012-08-26)开始,您可以使用$prev (或$xstar:prev)作为-i-a-s的参数,以引用最后插入的节点集。请参阅doc/xmlstarlet.txtexamples/ed-backref1examples/ed-backref2examples/ed-backref-delete文件中的XMLStarlet源代码中的示例。您不再需要使用这样的技巧:插入具有临时元素名称的元素,然后在末尾重命名它。在展示如何定义一个变量来引用先前创建的注释时,示例examples/ed-backref2特别有用,这样您就不需要像使用$prev/..这样的技巧来“导航”出节点。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5954168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档