-1

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>
AhmFM
  • 1,552
  • 3
  • 23
  • 53
  • Your question is unclear; for example, in the "before" file you have ``; but it's not in the "after" file. So are you making other changes as well? – Jack Fleeting Feb 27 '23 at 23:14

1 Answers1

0

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
Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45
  • Will your solution work if the node I need to insert is at 8009th line? Basically can we do it dynamic instead of being dependent on line number like insert if missing kind of logic? Because my original file is like 25k lines and missing that one node. – AhmFM Feb 28 '23 at 15:58
  • @AhmFM In principle - yes; but it's not about the line number as such (that's irrelevant), it's about the **position** of the element to be inserted inside the collection of elements. In your sample xml, you have two `` elements and the new element was inserted after the first (position 1, in xpath (not 0)). So you need to know in advance where in that order you want to insert the new element. – Jack Fleeting Feb 28 '23 at 16:04
  • Got it. Thanks but it should skip if there is one already correct and not over write? Am trying your solution now. – AhmFM Feb 28 '23 at 16:49
  • unfortunaltely did not work. I am still getting same error as my post `11.40: Opening and ending tag mismatch: coverage line 4 and file` – AhmFM Feb 28 '23 at 17:44
  • your code works when i manually set in the missing node then it enters the element so that implies my xml file is valid except that it is missing that node that we are trying to insert. so seems like I will have to use SED to insert though it is not preferred? – AhmFM Feb 28 '23 at 18:02
  • @AhmFM First, don't use SED or anything like that on xml; always use an xml parser (google to see why). Second, your error implies your actual xml is not well formed (as I mention in the answer). With a well-formed xml (like you had before you edited the question), the insertion should work without a hitch. – Jack Fleeting Feb 28 '23 at 18:15
  • trust me i did a lot of google and then only posted here. regarding malformed can you atleast indicate where is it malformed? because same exact works if i manually place missing `` and run your code. may be my error means `xmlstarlet` needs a proper xml to edit? where as my xml is missing node? – AhmFM Feb 28 '23 at 19:07
  • @AhmFM xmlstartlet (and every other xml parser in any language) **absolutely** requires a well-formed xml and will raise an error message otherwise. If that happens, you need to fix the xml, not try workarounds because, although they may work on one occasion, they will eventually fail. So you need to face the problem head on. The error you quote (`11.40: Opening and ending tag mismatch: coverage line 4 and file`) shows you what the problem is and on which line it shows up. That's where you need to start troubleshooting. – Jack Fleeting Feb 28 '23 at 19:55
  • i doubt ln4 has the problem because again my xml works with your code IF i manually put in the missing node there at line at 8th line. but if am manually inserting then what is the need anyways. so my problem here in this post is `ADD THE MISSING NODE in MALFORMED XML ?` if you are calling my xml as malformed based no missing node. – AhmFM Feb 28 '23 at 20:31