I am trying to modify the server.xml file of the Apache Tomcat
.
I would like to add a new element exactly after the last Connector
definition but my solution adds the new content at the end of the Service
, not after the last Connector
.
This is my XML:
(I removed the irrelevant attributes and elements from the real XML to make it more readable)
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.aaa"/>
<Listener className="org.bbb" SSLEngine="on"/>
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"/>
<!-- INSERT A NEW CONNECTOR HERE -->
<Engine name="Catalina" defaultHost="localhost">
<Realm className="aa">...</Realm>
</Engine>
</Service>
</Server>
My xmlstarlet
code inserts the desired content, but the position of the new Connector
element is wrong.
xmlstarlet:
xmlstarlet edit \
-s "//Server/Service[last()]" -t elem -n "Connector" \
-s "//Server/Service[last()]/Connector" -t attr -n port -v "443" \
-s "//Server/Service/Connector[@port='443']" -t attr -n protocol -v "org.apache.coyote.http11.Http11NioProtocol" \
1.xml
Result:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.aaa"/>
<Listener className="org.bbb" SSLEngine="on"/>
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="aa">...</Realm>
</Engine>
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"/>
</Service>
</Server>
But I want to have the new Connector
after the existing one:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.aaa"/>
<Listener className="org.bbb" SSLEngine="on"/>
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"/>
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"/>
<Engine name="Catalina" defaultHost="localhost">
<Realm className="aa">...</Realm>
</Engine>
</Service>
</Server>
What I missed in my code?
CodePudding user response:
Try:
xmlstarlet edit\
--append /Server/Service/Connector --type elem -n "Connector" \
--insert '/Server/Service//Connector[last()]' -t attr -n "port" -v "443" \
--insert '/Server/Service//Connector[last()]' -t attr -n "protocol" -v "org.apache.coyote.http11.Http11NioProtocol" \
1.xml
CodePudding user response:
With xmlstarlet edit
option -s
adds a node as last child,
-i
as preceding sibling, and -a
as following sibling, to each
member of their XPath argument.
With -t attr
they all add an attribute and have no influence on
attribute order.
xmlstarlet edit \
-a '/Server/Service[@name="Catalina"]/Connector[last()]' -t elem -n 'Connector' \
--var T '$prev' \
-s '$T' -t attr -n port -v '443' \
-s '$T' -t attr -n protocol -v 'org.apache.coyote.http11.Http11NioProtocol' \
file.xml
--var
defines a named variable, and the back reference $prev
variable (aka $xstar:prev
) refers to the node(s) created by the most
recent -s
, -i
, or -a
option which all define or redefine it
(see xmlstarlet.txt
for examples of --var
and $prev
).