inserting missing node with attributes in xml file at a specific line only

126 views Asked by At

Team,

I have below xml file which is missing a node at line 9. so I need to insert it and not anywhere else.

line to insert

<file branch-rate="0.0" complexity="0" path="src/common/test2.go" ......>

xml file i have that is missing node is below

<?xml version="1.0" ?>
<!DOCTYPE coverage
  SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-04.dtd'>
<coverage branch-rate="0.0" branches-covered="0" branches-valid="0" complexity="0" line-rate="0.5423496311641774" lines-covered="77492" lines-valid="142882" timestamp="1677260258" version="1">
                <file branch-rate="0.0" complexity="0" path="src/common/test1.go" line-rate="0.0" name="src.common.test1.go">
                        <lineToCover branch="false" covered="false" lineNumber="15"/>
                        <lineToCover branch="false" covered="false" lineNumber="16"/>
                </file>
                        <lineToCover branch="false" covered="false" lineNumber="17"/>
                        <lineToCover branch="false" covered="false" lineNumber=“18”/>
                <file branch-rate="0.0" complexity="0" path="src/common/test3.go" line-rate="0.0" name="src.common.test3.go">
                        <lineToCover branch="false" covered="false" lineNumber="19”/>
                        <lineToCover branch="false" covered="false" lineNumber=“20”/>
                </file>
</coverage>

I tried xmlStarlet with single attribute and that itself does not get inserted.

xmlstarlet ed --subnode "/coverage/file" --type elem -n file -v "" coverage-so.xml | xmlstarlet ed --insert //coverage/file --type attr -n "branch-rate"  -v "0.0" 

output

Command> xmlstarlet ed --subnode "/coverage/file" --type elem -n file -v "" coverage-so.xml | xmlstarlet ed --insert //coverage/file --type attr -n "branch-rate"  -v "0.0"
coverage-so.xml:11.40: Opening and ending tag mismatch: coverage line 4 and file
                                </file>
                                       ^
coverage-so.xml:12.5: Extra content at the end of the document
                                <file branch-rate="0.0" complexity="0" path="src/common/test3.go" line-rate=
                                ^
-:1.1: Document is empty

^

expected output Observe line 9 has new entry that needs to be inserted.

<?xml version="1.0" ?>
<!DOCTYPE coverage
  SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-04.dtd'>
<coverage branch-rate="0.0" branches-covered="0" branches-valid="0" complexity="0" line-rate="0.5423496311641774" lines-covered="77492" lines-valid="142882" timestamp="1677260258" version="1">
                <file branch-rate="0.0" complexity="0" path="src/common/test1.go" line-rate="0.0" name="src.common.test1.go">
                        <lineToCover branch="false" covered="false" lineNumber="15"/>
                        <lineToCover branch="false" covered="false" lineNumber="16"/>
                </file>
                                <file branch-rate="0.0" complexity="0" path="src/common/test2.go" line-rate="0.0" name="src.common.test2.go">
                                            <lineToCover branch="false" covered="false" lineNumber="17”/>
                        <lineToCover branch="false" covered="false" lineNumber=“18”/>
                                </file>
                <file branch-rate="0.0" complexity="0" path="src/common/test3.go" line-rate="0.0" name="src.common.test3.go">
                        <lineToCover branch="false" covered="false" lineNumber="19”/>
                        <lineToCover branch="false" covered="false" lineNumber=“20”/>
                                </file>
</coverage>
1

There are 1 answers

9
Jack Fleeting On

The xml files in your question still have issues and are not well-formed, but I believe you are looking for something like this. Note that this needs to be done in several steps:

xmlstarlet edit \
#append a new element to the original xml in the appropriate position:
--append '//file[1]' -t elem -n "file" \
#create a new variable name referring to the previously appended element
--var newb '$prev' \
#insert a series of attributes and attribute values to the new element
--insert '$newb' -t attr -n "branch-rate" -v "0.0" \
--insert '$newb' -t attr -n "complexity" -v "0" \
--insert '$newb' -t attr -n "path" -v "src/common/test2.go" \
--insert '$newb' -t attr -n "line-rate" -v "0.0" \
#finally move the stray lineToCover elements inside the new element:
--move '//lineToCover[@lineNumber="17"]' '//file[2]' \
--move '//lineToCover[@lineNumber="42"]' '//file[2]' \
file.xml