0

I want to write a script to iterate over each element "NewTempP" with attributes and child element and copy the structure to element "fig" as child element. "NewTempP" and "fig" are siblings.

Xml file:

<sec>
    <NewTempP  mimetype="image" mime-subtype="jpeg" xlink:href="image1.jpeg">
            <alt-text>Describes a picture</alt-text>
        </NewTempP >
        <p>test</p>
        <fig> </fig>
    <NewTempP  mimetype="image" mime-subtype="png" xlink:href="image1.png">
           <alt-text>Describes a picture</alt-text>
    </NewTempP >
    <p>test</p>
     <fig> </fig>
   ……..
<sec>

What I did:

xmlstarlet ed -L -P -u "//fig[preceding-sibling::*[1][self:: NewTempP/@*]]/inline-graphic" -x "string(../preceding-sibling::NewTempP [1]/@*)" test.xml

It does not work.

The result supposed to look like this:

<sec>
    <NewTempP  mimetype="image" mime-subtype="jpeg" xlink:href="image1.jpeg">
            <alt-text>Describes a picture</alt-text>
        </NewTempP >
        <p>test</p>
        <fig>
           <NewTempP  mimetype="image" mime-subtype="jpeg" xlink:href="image1.jpeg">
              <alt-text>Describes a picture</alt-text>
          </NewTempP >
       </fig>
       <NewTempP  mimetype="image" mime-subtype="png" xlink:href="image1.png">
           <alt-text>Describes a picture</alt-text>
       </NewTempP >
       <p>test</p>
       <fig>
         <NewTempP  mimetype="image" mime-subtype="png" xlink:href="image1.png">
              <alt-text>Describes a picture</alt-text>
        </NewTempP >
      </fig>
   ……..
<sec>
2
  • XML samples should be well formed. This is not well formed <p>test</fig> Commented Apr 23, 2024 at 14:38
  • Correced <p>test</fig> to <p>test</p> Commented Apr 23, 2024 at 15:55

1 Answer 1

0

Looks like you're trying to modify my last answer but don't quite know how XPath works.

This xpath:

//fig[preceding-sibling::*[1][self:: NewTempP/@*]]/inline-graphic

doesn't work for these reasons:

  • the first preceding sibling (preceding-sibling::*[1]) of each fig in your example is p; not NewTempP.
  • your sample input does not have any inline-graphic elements.

This xpath:

string(../preceding-sibling::NewTempP [1]/@*)

doesn't work for these reasons:

  • the output of string() is a string; not a copy of the node like you requested.
  • if you're trying to copy the element, selecting its attributes (@*) will not work.
  • going up to the parent level (..) before trying to select the preceding-sibling NewTempP won't work because NewTempP is not a sibling of sec

You don't explain what the actual logic should be in your selections, but here's an option that just selects the first preceding sibling NewTempP...

xmlstarlet ed -P -u "//fig[preceding-sibling::NewTempP]" -x "preceding-sibling::NewTempP[1]" test.xml

Output (I left out the -L for modifying the input file in-place)...

<sec>
    <NewTempP mimetype="image" mime-subtype="jpeg" xlink:href="image1.jpeg">
        <alt-text>Describes a picture</alt-text>
    </NewTempP>
    <p>test</p>
    <fig><NewTempP mimetype="image" mime-subtype="jpeg" xlink:href="image1.jpeg">
        <alt-text>Describes a picture</alt-text>
    </NewTempP></fig>
    <NewTempP mimetype="image" mime-subtype="png" xlink:href="image1.png">
        <alt-text>Describes a picture</alt-text>
    </NewTempP>
    <p>test</p>
    <fig><NewTempP mimetype="image" mime-subtype="png" xlink:href="image1.png">
        <alt-text>Describes a picture</alt-text>
    </NewTempP></fig>
    ...
</sec>
Sign up to request clarification or add additional context in comments.

1 Comment

Great. The script works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.