c++xmlpugixml

Add XML contained in string as XML nodes to existing pugixml tree


I have a configuration file saver/loader. In addition to the expected data, there is a <CustomData> node. When saving the node, we'd simply have a std::string _customData and add it to the node, like this:

  pugi::xml_document doc;
  pugi::xml_node config = doc.append_child("OurConfig");

  // save custom data
  pugi::xml_node customData = config.append_child("CustomData");
  customData.append_child(pugi::node_pcdata).set_value(_customData);

Our _customData was base64 encoded XML. It is provided from another part of the application. It must be a string, since the other part of the application uses different programming language (C#). As you can imagine, that became annoying, because it wasn't human readable. First step to fix this was simply to get rid of base64 in the app that provides _customData. So now we have readable version, which looks like this:

    <?xml version="1.0"?>
    <OurConfig>
        <CustomData>&lt;CfgRoot&gt;
&lt;SomeValue name="External setting for foo" value="Foo"/&gt;
&lt;SomeValue name="External setting for bar" value="Bar"/&gt;
&lt;/CfgRoot&gt;</CustomData>
    </OurConfig>

But it could probably improve if the custom data was directly appended to XML tree instead of as string value. How can I append XML string as XML and not as string to pugixml tree?

Ie. the output I'd like:

<?xml version="1.0"?>
<OurConfig>
    <CustomData>
    <CfgRoot>
      <SomeValue name="External setting for foo" value="Foo"/>
      <SomeValue name="External setting for bar" value="Bar"/>
    </CfgRoot>
  </CustomData>
</OurConfig>

Solution

  • In the docs, there are three methods listed. I used the first one, making a convenience function like this:

    bool AppendXMLString(pugi::xml_node target, const std::string& srcString)
    {
      // parse XML string as document
      pugi::xml_document doc;
      if (!doc.load_buffer(srcString.c_str(), srcString.length()))
        return false;
    
      for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
        target.append_copy(child);
      return true;
    }