0

I'm trying to figure out how to insert a text in an xml file with sed command. I started to try some basic commands with sed :

sed -i -e ' <property name="prop1" ref="ANOTHER_BEAN" /> ' my_config_file.xml  

it's adding this line but not in the position that I want

The problem for my specific case is that the text should be add to a certain position (certain bean as it's a java config file)

Example

 <bean id="BEAN_ID_1"
    class="com.toto.BeanClass1"
    scope="prototype">
    <property name="prop1" ref="ANOTHER_BEAN_1" />
    <property name="prop2" ref="BEAN1" />
 </bean>

<bean id="BEAN_ID_2"
    class="com.toto.BeanClass2"
    scope="prototype">
    <property name="prop_1" ref="ANOTHER_BEAN_2" />
    <property name="prop_2" ref="BEAN2" />
 </bean>

I want to add this property to the bean named 'BEAN_ID_1' before the enclosing tag

 <property name="property" ref="ANOTHER_BEANXXX" />

so the output will be :

 <bean id="BEAN_ID_1"
    class="com.toto.BeanClass1"
    scope="prototype">
    <property name="prop1" ref="ANOTHER_BEAN_1" />
    <property name="prop2" ref="BEAN1" />
    <property name="property" ref="ANOTHER_BEANXXX" />
 </bean>

<bean id="BEAN_ID_2"
    class="com.toto.BeanClass2"
    scope="prototype">
    <property name="prop_1" ref="ANOTHER_BEAN_2" />
    <property name="prop_2" ref="BEAN2" />
 </bean> 

PS: I can't rely on line number since in production I have no Idea how is the file

Can anybody help me on this ? Thanks a lot

2 Answers 2

2

Using an XML parser/editor to edit your XML is always a safer approach than trying to fudge it with sed.

I've fixed up your XML sample by wrapping it all in <beans>...</beans> so that it's valid XML. And here is a solution using xmlstarlet:

xmlstarlet edit --subnode '//bean[@id="BEAN_ID_1"]' -t elem -n property --var this '$prev' --insert '$this' -t attr -n name -v property --insert '$this' -t attr -n ref -v 'ANOTHER_BEANXXX' configFile

Output

<?xml version="1.0"?>
<beans>
  <bean id="BEAN_ID_1" class="com.toto.BeanClass1" scope="prototype">
    <property name="prop1" ref="ANOTHER_BEAN_1"/>
    <property name="prop2" ref="BEAN1"/>
    <property name="property" ref="ANOTHER_BEANXXX"/>
  </bean>
  <bean id="BEAN_ID_2" class="com.toto.BeanClass2" scope="prototype">
    <property name="prop_1" ref="ANOTHER_BEAN_2"/>
    <property name="prop_2" ref="BEAN2"/>
  </bean>
</beans>

Explanation of the xmlstarlet line:

# Edit the XML, writing the result to stdout
xmlstarlet edit

# Create a subnode called "property" of "//bean" having an attribute id="BEAN_ID_1"
--subnode '//bean[@id="BEAN_ID_1"]' -t elem -n property

# Identify this new element as "this"
--var this '$prev'

# Insert an attribute called "name" with a value "property" into the new element
--insert '$this' -t attr -n name -v property

# Insert an attributed called "ref" with a value "ANOTHER_BEANXXX" into the new element
--insert '$this' -t attr -n ref -v 'ANOTHER_BEANXXX'

# XML source file
configFile
2
1

You might consider using an xml parser for xml; would be more robust.

But maybe something like this?

sed -i '/<bean id="BEAN_ID_1"/,/<\/bean>/ s/<\/bean>/   <property name="property" ref="ANOTHER_BEANXXX" \/>\n<\/bean>/' my_config_file.xml

This means within the range starting with <bean id="BEAN_ID_1" and ending with </bean>, insert the line <property name="property" ref="ANOTHER_BEANXXX" /> right before </bean>.

1
  • Thanks a lot @frabjous !
    – pietà
    Mar 21, 2022 at 17:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .