I had a similar problem: I had a Tomcat configuration file (server.xml), and had to insert a <Resource>
tag with pre-defined attributes into the <GlobalNamingResources>
section.
Here is how it looked before:
<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>
Here is what I wanted to achieve:
<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&useUnicode=true&characterEncoding=utf-8"
username="DBUSER"
password="DBPASS"
maxActive="150"
maxIdle="10"
initialSize="10"
validationQuery="SELECT 1"
testOnBorrow="true" />
</GlobalNamingResources>
Here is how I did it (snippet from a shell script):
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
The trick is to temporarily give a unique name to the new element, so that it can be found later with an XPATH expression. After all attributes have been added, the name is changed back to Resource (with -r).
The meaning of the other xmlstarlet options:
-P (or --pf) - preserve original formatting
-S (or --ps) - preserve non-significant spaces
-L (or --inplace) - edit file inplace
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…