htmlxml-namespacesxmlstarletxmllinthtml-xml-utils

Replace anything inside a HTML tag ID


Have searched all over Stackoverflow and Google, and the closest answer:

sed -i -e 's|<element id="lastupdate">\([0-9]\{0,\}\)</element>|<element id="lastupdate">'"$(date -d @${contents})"'</element>|g' /var/www/html/index.html

works only when the tag's content is empty. If it is already changed, it can't be used anymore.

The idea is to change anything inside this tag id, and not only when it is empty.

Here's a good answer about reading anything inside a tag id, using awk: https://stackoverflow.com/a/13148004/5623661. But it works only for reading (with awk) and not for appending/replacing (using sed).

Another idea is to not only having a way to replace: but another to, alternatively, append into anything inside the given tag.

Is it possible to use a tool that works for HTML instead of one specific made for XML? Have tried:

Input: xmlstarlet ed --update '//element[@id="daipeg"]' --value 'new' index.html

Output:

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8"/>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Status - Floflis</title>
    <link rel="shortcut icon" href="icon.ico" type="image/x-icon"/>
    <link rel="icon" href="icon.ico" type="image/x-icon"/>
  </head>
  <body><h1>Floflis Status</h1><ul><li><p>Is DAI pegged to USD? <b><element id="daipeg">No</element></b></p></li><li><p>DAI now worth <b><element id="daiusd"/> USD</b></p></li></ul><p>Last updated in <element id="lastupdate"/> (updates every 5 minutes).</p><a href="https://floflis.github.io/" target="_blank">Main site</a> | <a href="https://floflis.github.io/blog" target="_blank">Blog</a> | <a href="https://floflis.github.io/docs" target="_blank">Documentation</a> | <a href="./api.html">DEV</a>
</body>
</html>

Desired result: changing the "No" inside <element id="daipeg">No</element> to "new", directly into the index.html file.


Solution

  • (Responding to tag, I used version 1.6.1.)

    If you fix a namespace issue and add an --inplace option you're there (replacing element value):

    test "${bettersorrythansafe}" || cp file.xhtml file.xhtml.was
    xmlstarlet ed --inplace -N X='http://www.w3.org/1999/xhtml' \
        --update '//X:element[@id="daipeg"]' --value 'new' file.xhtml
    

    Or, with short options and a shortcut for the default namespace:

    xmlstarlet ed -L -u '//_:element[@id="daipeg"]' -v 'new' file.xhtml
    

    Note that the --inplace option is mentioned in xmlstarlet.txt but not in the user's guide. For more on the _ namespace shortcut see the user's guide ch. 5.

    To append to the value, for example:

    xmlstarlet ed -L -N X='http://www.w3.org/1999/xhtml' \
        --var peg '//X:element[@id="daipeg"]' \
        --var res "$((3 * 7 * 2))" \
        -u '$peg' -x 'concat($peg," and then ",$res)' file.xhtml