41

I'm trying to write an XML parser, parsing the XML file to a boost::property_tree and came upon this problem. How can I check (quickly) if a child of a certain property exists?

Obviously I could iterate over all children using BOOST_FOREACH - however, isn't there a better solution to this?

Null
  • 1,940
  • 9
  • 24
  • 29
paul23
  • 7,226
  • 9
  • 44
  • 108

4 Answers4

54
optional< const ptree& > child = node.get_child_optional( "possibly_missing_node" );
if( !child )
{
  // child node is missing
}
RobH
  • 3,139
  • 1
  • 20
  • 27
  • in order to get your example to work I had to remove the 'const' - could you please explain why you use 'const' here ? – serup Sep 14 '16 at 08:43
  • For safety. When reading configuration there can be little reason ever to modify values. A quick search shows me that ptree still has (in boost 1.61.0) a get_child_optional overload which returns optional, so your error will be related to what you do with the value subsequently. – RobH Sep 19 '16 at 10:33
  • I tried several alternatives and ended up using boost::optional. Note that you can also access the data directly using the code from the Boost documentation: See [Boost docs here](https://www.boost.org/doc/libs/1_41_0/doc/html/boost_propertytree/accessing.html). Try this: boost::optional v = pt.get_optional("a.path.to.float.value"); – eatyourgreens Jun 11 '18 at 08:35
23

Here's a couple of other alternatives:

if( node.count("possibliy_missing") == 0 )
{
   ...
}

ptree::const_assoc_iterator it = ptree.find("possibly_missing");
if( it == ptree.not_found() )
{
   ...
}
Michael Anderson
  • 61,385
  • 7
  • 119
  • 164
  • 2
    I like the 2nd one ... more stl style – anhoppe Nov 10 '15 at 08:52
  • 1
    I find it interesting to note that unlike the get<> method the find method does not provide support for find("SubNode.Attribute"). You have to manually get the SubNode child in the ptree and run find on the child instance, – anhoppe Nov 10 '15 at 10:21
  • 2
    node.count will also not work for nested keys, such as "child.subchild". The only thing that I found works so far is the node.get_child_optional, as in the below answer https://stackoverflow.com/a/25389349/844728 – Greg Kramida Nov 14 '19 at 10:26
7

Include this:

#include <boost/optional/optional.hpp>

Remove the const:

boost::optional< ptree& > child = node.get_child_optional( "possibly_missing_node" );
if( !child )
{
  // child node is missing
}
Avery
  • 2,035
  • 4
  • 33
  • 32
  • 6
    While your answer is valid, you copied most of another answer (with no disclosure!) that was accepted and almost 3 years old. Can you at least explain why you made the changes you did? This is likely better served as a comment. – Avery Aug 19 '14 at 17:28
  • 2
    I voted you down since you are not adding to the solution - perhaps if you had changed more than just removing the const, then I would have voted up – serup Sep 14 '16 at 09:19
1

While these solutions might appear to avoid iterating over the tree, just keep in mind that under the covers they are still doing exactly that, so you are making your algorithm potentially n^2... if you are concerned about performance and have memory to spare, you could use a map container for quick lookups.

Rich
  • 829
  • 8
  • 15