In the XML tree model, text elements are nodes as well. This makes sense when you have mixed content elements: <a>some<b/>text<c/>nodes</a>.
Basically:
#include <rapidxml/rapidxml_print.hpp>
#include <rapidxml/rapidxml_utils.hpp>
int main() {
    rapidxml::file<> xmlFile("Original.xml");
    rapidxml::xml_document<> doc;
    doc.parse<0>(xmlFile.data());
    auto root      = doc.first_node();
    auto metadata  = root->first_node();
    auto text_node = metadata->first_node();
    text_node->value("Did the changing");
    std::ofstream newXmlFile("New.xml");
    newXmlFile << doc;
}
But wait, there's more
Sadly, this is a problem unless your input has exactly the expected properties.
Assuming this ok sample:
char sample1[] = R"(<root><metadata>Trying to change this</metadata></root>)";
If metadata element were empty, you'd crash:
char sample2[] = R"(<root><metadata></metadata></root>)";
char sample3[] = R"(<root><metadata/></root>)";
Indeed this triggers ASAN failures:
/home/sehe/Projects/stackoverflow/test.cpp:17:25: runtime error: member access within null pointer of type 'struct xml_node'
/home/sehe/Projects/stackoverflow/test.cpp:17:25: runtime error: member call on null pointer of type 'struct xml_base'
/usr/include/rapidxml/rapidxml.hpp:762:24: runtime error: member call on null pointer of type 'struct xml_base'
/usr/include/rapidxml/rapidxml.hpp:753:21: runtime error: member access within null pointer of type 'struct xml_base'
AddressSanitizer:DEADLYSIGNAL
If there's a surprise, it will .... do surprising things!
char sample4[] = R"(<root><metadata><surprise/></metadata></root>)";
Ends up erroneously generating:
<root>
        <metadata>
                <surprise>changed</surprise>
        </metadata>
</root>
And that's not the end of it:
#include <rapidxml/rapidxml_print.hpp>
#include <rapidxml/rapidxml_utils.hpp>
#include <iostream>
namespace {
    char sample1[] = R"(<root><metadata>Trying to change this</metadata></root>)";
    char sample2[] = R"(<root><metadata><surprise/></metadata></root>)";
    char sample3[] = R"(<root><metadata>mixed<surprise/>bag</metadata></root>)";
    char sample4[] = R"(<root><metadata><![CDATA[mixed<surprise/>bag]]></metadata></root>)";
    char sample5[] = R"(<root><metadata><!-- comment please -->outloud<!-- hidden --></metadata></root>)";
    //These crash:
    //char sampleX[] = R"(<root><metadata></metadata></root>)";
    //char sampleY[] = R"(<root><metadata/></root>)";
}
int main() {
    for (char* xml : {sample1, sample2, sample3, sample4, sample5}) {
        std::cout << "\n=== " << xml << " ===\n";
        rapidxml::xml_document<> doc;
        doc.parse<0>(xml);
        auto root      = doc.first_node();
        auto metadata  = root->first_node();
        auto text_node = metadata->first_node();
        text_node->value("changed");
        print(std::cout << " --> ", doc, rapidxml::print_no_indenting);
        std::cout << "\n";
    }
}
Prints
=== <root><metadata>Trying to change this</metadata></root> ===
 --> <root><metadata>changed</metadata></root>
=== <root><metadata><surprise/></metadata></root> ===
 --> <root><metadata><surprise>changed</surprise></metadata></root>
=== <root><metadata>mixed<surprise/>bag</metadata></root> ===
 --> <root><metadata>changed<surprise/>bag</metadata></root>
=== <root><metadata><![CDATA[mixed<surprise/>bag]]></metadata></root> ===
 --> <root><metadata><![CDATA[changed]]></metadata></root>
=== <root><metadata><!-- comment please -->outloud<!-- hidden --></metadata></root> ===
 --> <root><metadata>changed</metadata></root>
HOW TO GET IT ROBUST?
- Firstly, use queries to find your target. Sadly rapidxml doesn't support this; See What XML parser should I use in C++? 
- Secondly, check the node type before editing 
- Thirdly, replace the entire node if you can, that makes you independent of what was previously there 
- Lastly, be sure to actually allocate your new node from the document so you don't get lifetime issues. -  auto root = doc.first_node();
 if (auto* old_meta = root->first_node()) {
     assert(old_meta->name() == std::string("metadata"));
     print(std::cout << "Removing metadata node: ", *old_meta, fmt);
     std::cout << "\n";
     root->remove_first_node();
 }
 auto newmeta = doc.allocate_node(rapidxml::node_element, "metadata", "changed");
 root->prepend_node(newmeta);
 
PUTTING IT ALL TOGETHER:
#include <rapidxml/rapidxml.hpp>
#include <rapidxml/rapidxml_print.hpp>
#include <rapidxml/rapidxml_utils.hpp>
#include <iostream>
namespace {
    std::string cases[] = {
     R"(<root><metadata>Trying to change this</metadata></root>)",
     R"(<root><metadata><surprise/></metadata></root>)",
     R"(<root><metadata>mixed<surprise/>bag</metadata></root>)",
     R"(<root><metadata><![CDATA[mixed<surprise/>bag]]></metadata></root>)",
     R"(<root><metadata><!-- comment please -->outloud<!-- hidden --></metadata></root>)",
     R"(<root>
  <metadata>Trying to change this</metadata>
  <body>
    <salad>Greek Caesar</salad>
   </body>
</root>)",
     //These no longer crash:
     R"(<root><metadata></metadata></root>)",
     R"(<root><metadata/></root>)",
     // more edge-cases in the predecessor chain
     R"(<root></root>)",
     R"(<root><no-metadata/></root>)",
     R"(<bogus/>)",
    };
}
int main() {
    auto const fmt = rapidxml::print_no_indenting;
    for (auto& xml : cases) {
        std::cout << "Input: " << xml << "\n";
        rapidxml::xml_document<> doc;
        doc.parse<0>(xml.data());
        if (auto root = doc.first_node()) {
            if (root->name() == std::string("root")) {
                if (auto* old_meta = root->first_node()) {
                    if (old_meta->name() == std::string("metadata")) {
                        root->remove_first_node();
                    } else {
                        std::cout << "WARNING: Not removing '" << old_meta->name() << "' element where 'metadata' expected\n";
                    }
                }
                auto newmeta = doc.allocate_node(rapidxml::node_element, "metadata", "changed");
                root->prepend_node(newmeta);
            } else {
                std::cout << "WARNING: '" << root->name() << "' found where 'root' expected\n";
            }
        }
        
        print(std::cout << "Output: ", doc, fmt);
        std::cout << "\n--\n";
    }
}
Prints
Input: <root><metadata>Trying to change this</metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><metadata><surprise/></metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><metadata>mixed<surprise/>bag</metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><metadata><![CDATA[mixed<surprise/>bag]]></metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><metadata><!-- comment please -->outloud<!-- hidden --></metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root>
  <metadata>Trying to change this</metadata>
  <body>
    <salad>Greek Caesar</salad>
   </body>
</root> ===
Output: <root><metadata>changed</metadata><body><salad>Greek Caesar</salad></body></root>
--
Input: <root><metadata></metadata></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><metadata/></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root></root> ===
Output: <root><metadata>changed</metadata></root>
--
Input: <root><no-metadata/></root> ===
WARNING: Not removing 'no-metadata' element where 'metadata' expected
Output: <root><metadata>changed</metadata><no-metadata/></root>
--
Input: <bogus/> ===
WARNING: 'bogus' found where 'root' expected
Output: <bogus/>
--
SUMMARY
XML is extensible. It's Markup. It's Language. It's not simple :)
the definition of hell... interesting. – sehe Jul 10 '20 at 15:50