Solución:
Tuve un problema similar: tenía un archivo de configuración de Tomcat (server.xml) y tuve que insertar un <Resource>
etiqueta con atributos predefinidos en el <GlobalNamingResources>
sección.
Así es como se veía antes:
<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>
Esto es lo que quería lograr:
<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>
Así es como lo hice (fragmento de un script de shell):
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
El truco consiste en dar temporalmente un nombre único al nuevo elemento, de modo que se pueda encontrar más tarde con una expresión XPATH. Una vez que se han agregado todos los atributos, el nombre se cambia de nuevo a Recurso (con -r).
El significado de las otras opciones de xmlstarlet:
-P (or --pf) - preserve original formatting
-S (or --ps) - preserve non-significant spaces
-L (or --inplace) - edit file inplace
Usar -s
(o --subnode
) en lugar de -i
. Con respecto a la bonificación, no puede insertar un elemento con un atributo directamente, pero dado que cada operación de edición se realiza en secuencia, para insertar un elemento y luego agregar un atributo:
> 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>
A partir de la versión 1.4.0 de XMLStarlet (con fecha del 26 de agosto de 2012), puede utilizar $prev
(o $xstar:prev
) como argumento para -i
, -a
, y -s
para hacer referencia al último conjunto de nodos insertado. Vea los ejemplos en el código fuente de XMLStarlet en los archivos doc/xmlstarlet.txt
, examples/ed-backref1
, examples/ed-backref2
, y examples/ed-backref-delete
. Ya no necesita usar el truco de insertar el elemento con un nombre de elemento temporal y luego renombrarlo al final. El ejemplo examples/ed-backref2
es particularmente útil para mostrar cómo definir una variable para usar para referirse a una (la) nota creada previamente para que no necesite hacer trucos como $prev/..
para “navegar” fuera de un nodo.