Search code examples
xmlxpathxmlstarlet

xmlpath and one or more series of xmlstarlet commands to edit XML child element value based on instances of repeated parent element


Input xml:

 <?xml version="1.0" encoding="utf-8"?>
 <testsuites>
    <testsuite>
        <testcase classname='Formatting Test' name='Test_01.swift'>
            <failure message='Function parameters should be aligned vertically'>warning: Line:10 </failure>
        </testcase>
        <testcase classname='Formatting Test' name='Test_02.swift'>
            <failure message='Function parameters should be aligned vertically'>warning: Line:11 </failure>
        </testcase>
    </testsuite>
</testsuites>

Output:

<?xml version="1.0" encoding="utf-8"?>
<testsuites>
    <testsuite>
        <testcase classname='Formatting Test' name='Test_01.swift'>
            <failure message='Function parameters should be aligned vertically'>debug_line_1 ></failure>
        </testcase>
        <testcase classname='Formatting Test' name='Test_02.swift'>
            <failure message='Function parameters should be aligned vertically'>debug_line_2 ></failure>
        </testcase>
    </testsuite>
</testsuites>

I know this will get me the number of nodes elements testcase:

`xmlstarlet sel  -t -c "count(//*/testcase)" filename.xml`

on bash the above line would return: 2

I need an xpath (or more if cant be done is one pass) expressions with a function that I could use to replace the child node element value failure with a hardcoded one that goes according to the instance of the parent test case. For example (as per output):

Instance 1 of

testcase classname='Formatting Test' name='Test_01.swift'

Original value of

failure message='Function parameters should be aligned vertically'

is warning: Line:10

New Value will be:

debug_line_1

For all consecutive node elements testcase its children value should increase by 1:

Next testcase element value would be

debug_line_2

And so forth...

Any help is appreciated.


Solution

  • It's not very efficient, but you could count preceding testcase elements...

    xmlstarlet ed -u '//testcase/*' -x 'concat("debug_line_",count(preceding::testcase)+1)' input.xml