I am trying to add attribute under an existing attribute in an XML file. I have been using xmlstarted for edit but never used it for update. Would be helpful is someone tell how to add a new attr and an element under that new attrb -
Here is the snippet of my xml file -
Here is what i usually does to edit the sub elements with the hel;p of xmlstarlet-
xmlstarlet edit --inplace -u "/allocations/queue[@name='root']/queue[@name='paas_api_q1']/queue[@name='child1_sq1']/minResources" --value "$value" myfile.xml
Before -
<?xml version="1.0"?>
<allocations>
<queue name="root">
<aclSubmitApps> bddbagrp,mapr</aclSubmitApps>
<aclAdministerApps> bddbagrp,root,mapr,trmte_id</aclAdministerApps>
<schedulingPolicy>drf</schedulingPolicy>
<defaultMinSharePreemptionTimeout>60</defaultMinSharePreemptionTimeout>
<fairSharePreemptionTimeout>60</fairSharePreemptionTimeout>
<queue name="paas_api_q1">
<minResources>90000 mb,15 vcores,2 disks</minResources>
<maxResources>135000 mb,22 vcores,3 disks</maxResources>
<queue name="child1_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>264000 mb,44 vcores,8 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
</queue>
</queue>
<queuePlacementPolicy>
<rule create="false" name="specified"/>
<rule name="reject"/>
</queuePlacementPolicy>
</allocations>
After it should look like this.. Here i am adding a new attribute under an existing attr - pass_api_q1 .
<!-- language: lang-xml -->
<?xml version="1.0"?>
<allocations>
<queue name="root">
<aclSubmitApps> bddbagrp,mapr</aclSubmitApps>
<aclAdministerApps> bddbagrp,root,mapr,trmte_id</aclAdministerApps>
<schedulingPolicy>drf</schedulingPolicy>
<defaultMinSharePreemptionTimeout>60</defaultMinSharePreemptionTimeout>
<fairSharePreemptionTimeout>60</fairSharePreemptionTimeout>
<queue name="paas_api_q1">
<minResources>90000 mb,15 vcores,2 disks</minResources>
<maxResources>135000 mb,22 vcores,3 disks</maxResources>
<queue name="child1_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>264000 mb,44 vcores,8 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
<queue name="child2_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>132000 mb,22 vcores,4 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
</queue>
</queue>
<queuePlacementPolicy>
<rule create="false" name="specified"/>
<rule name="reject"/>
</queuePlacementPolicy>
</allocations>
Any help/direction would be appreciated.
You could use a bunch of -i/-a/-s to add the new elements (see here), but I think it would be easier to use XSLT with tr
. You could put your elements in another file and pass it in as a parameter.
Example...
XML fragment to add (fragment.xml)
<?xml version="1.0"?>
<queue name="child2_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>132000 mb,22 vcores,4 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
XSLT (test.xsl)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="frag"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--If you wanted to make this stylesheet reusable, you could pass a new
value in for the "match" attribute by selecting this template by its
"name" value (@name='target').-->
<xsl:template match="queue[@name='paas_api_q1']" name="target">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="$frag"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
xmlstarlet command line
xmlstarlet tr test.xsl -p frag='document("fragment.xml")/*' input.xml
Output
<?xml version="1.0"?>
<allocations>
<queue name="root">
<aclSubmitApps> bddbagrp,mapr</aclSubmitApps>
<aclAdministerApps> bddbagrp,root,mapr,trmte_id</aclAdministerApps>
<schedulingPolicy>drf</schedulingPolicy>
<defaultMinSharePreemptionTimeout>60</defaultMinSharePreemptionTimeout>
<fairSharePreemptionTimeout>60</fairSharePreemptionTimeout>
<queue name="paas_api_q1">
<minResources>90000 mb,15 vcores,2 disks</minResources>
<maxResources>135000 mb,22 vcores,3 disks</maxResources>
<queue name="child1_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>264000 mb,44 vcores,8 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
<queue name="child2_sq1">
<minResources>66000 mb,11 vcores,2 disks</minResources>
<maxResources>132000 mb,22 vcores,4 disks</maxResources>
<aclSubmitApps> paas_opsauto_admin_unix</aclSubmitApps>
<aclAdministerApps> paas_opsauto_admin_unix</aclAdministerApps>
<label>allnodes||balanced</label>
</queue>
</queue>
</queue>
<queuePlacementPolicy>
<rule create="false" name="specified"/>
<rule name="reject"/>
</queuePlacementPolicy>
</allocations>