0

I have the following xml file:

<?xml version="1.0" encoding="UTF-8"?>
<sec>
  <NewTempP>xxx</NewTempP>
  <fig>
    <label></label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
  <NewTempP>aaaa</NewTempP>
  <fig>
    <label></label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
  <NewTempP>zzzz</NewTempP>
  <fig>
    <label></label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
....
</sec>

I wrote xmlstarlet in a bash script that iterates over each <NewTempP> element in the XML file, checks if it has an immediate following sibling <fig> with a child element <label>, and if so, copies the content of <NewTempP> to the corresponding <label>:

#!/bin/bash

# Path to your XML file
xmlfile="test.xml"

# Iterate over each <NewTempP> element
xmlstarlet sel -t -c "/sec/NewTempP" "$xmlfile" | while read -r newTempP; do
    # Extract the content of <NewTempP>
    content=$(echo "$newTempP" | xmlstarlet sel -t -v ".")

    # Check if there's an immediate following sibling <fig> with a child <label>
    figLabel=$(echo "$newTempP" | xmlstarlet sel -t -v "following-sibling::fig/label")

    if [ -n "$figLabel" ]; then
        # Update the <label> element with the content of <NewTempP>
        xmlstarlet ed - L --inplace -u "following-sibling::fig/label" -v "$content" "$xmlfile"
    fi
done

The script does not update <label> and no any error messages. What is wrong? The result should be:

<?xml version="1.0" encoding="UTF-8"?>
<sec>
  <NewTempP>xxx</NewTempP>
  <fig>
    <label>xxx</label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
  <NewTempP>aaaa</NewTempP>
  <fig>
    <label>aaaa</label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
  <NewTempP>zzzz</NewTempP>
  <fig>
    <label>zzzz</label>
    <caption>
      <p/>
    </caption>
    <graphic/>
  </fig>
....
</sec>

Thanks in advance.

Ofuuzo

1 Answer 1

0

I think the main issue is you're running two different xmlstarlet commands. When you run your second command and use the xpath following-sibling::fig/label, you've lost the context (following-sibling of what?).

You could do this with just a single xmlstarlet ed command...

command line:

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

output:

<?xml version="1.0"?>
<sec>
    <NewTempP>xxx</NewTempP>
    <fig>
        <label>xxx</label>
        <caption>
            <p/>
        </caption>
        <graphic/>
    </fig>
    <NewTempP>aaaa</NewTempP>
    <fig>
        <label>aaaa</label>
        <caption>
            <p/>
        </caption>
        <graphic/>
    </fig>
    <NewTempP>zzzz</NewTempP>
    <fig>
        <label>zzzz</label>
        <caption>
            <p/>
        </caption>
        <graphic/>
    </fig>
    ....
</sec>
Sign up to request clarification or add additional context in comments.

Comments

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.