@@ -434,119 +434,76 @@ void VerifyXML(const std::string& xml_text,
434434 const std::string ID = node->Attribute (" ID" ) ? node->Attribute (" ID" ) : " " ;
435435 const int line_number = node->GetLineNum ();
436436
437- if (name == " Decorator" )
437+ // Precondition: built-in XML element types must define attribute [ID]
438+ const bool is_builtin =
439+ (name == " Decorator" || name == " Action" || name == " Condition" ||
440+ name == " Control" || name == " SubTree" );
441+ if (is_builtin && ID.empty ())
438442 {
439- if (children_count != 1 )
440- {
441- ThrowError (line_number, " The tag <Decorator> must have exactly 1 "
442- " child" );
443- }
444- if (ID.empty ())
445- {
446- ThrowError (line_number, " The tag <Decorator> must have the "
447- " attribute [ID]" );
448- }
449- }
450- else if (name == " Action" )
451- {
452- if (children_count != 0 )
453- {
454- ThrowError (line_number, " The tag <Action> must not have any "
455- " child" );
456- }
457- if (ID.empty ())
458- {
459- ThrowError (line_number, " The tag <Action> must have the "
460- " attribute [ID]" );
461- }
443+ ThrowError (line_number,
444+ std::string (" The tag <" ) + name + " > must have the attribute [ID]" );
462445 }
463- else if (name == " Condition" )
446+
447+ if (name == " BehaviorTree" )
464448 {
465- if (children_count != 0 )
466- {
467- ThrowError (line_number, " The tag <Condition> must not have any "
468- " child" );
469- }
470- if (ID.empty ())
449+ if (ID.empty () && behavior_tree_count > 1 )
471450 {
472- ThrowError (line_number, " The tag <Condition> must have the "
473- " attribute [ID]" );
451+ ThrowError (line_number, " The tag <BehaviorTree> must have the attribute [ID]" );
474452 }
475- }
476- else if (name == " Control" )
477- {
478- if (children_count == 0 )
453+ if (registered_nodes.count (ID) != 0 )
479454 {
480- ThrowError (line_number, " The tag <Control > must have at least 1 "
481- " child " );
455+ ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree > must not use "
456+ " the name of a registered Node " );
482457 }
483- if (ID. empty () )
458+ if (children_count != 1 )
484459 {
485- ThrowError (line_number, " The tag <Control> must have the "
486- " attribute [ID] " );
460+ ThrowError (line_number, " The tag <BehaviorTree> with ID ' " + ID +
461+ " ' must have exactly 1 child " );
487462 }
488463 }
489464 else if (name == " SubTree" )
490465 {
491466 if (children_count != 0 )
492467 {
493- ThrowError (line_number, " <SubTree> should not have any child" );
494- }
495- if (ID.empty ())
496- {
497- ThrowError (line_number, " The tag <SubTree> must have the "
498- " attribute [ID]" );
468+ ThrowError (line_number,
469+ " <SubTree> with ID '" + ID + " ' should not have any child" );
499470 }
500471 if (registered_nodes.count (ID) != 0 )
501472 {
502- ThrowError (line_number, " The attribute [ID] of tag <SubTree> must "
503- " not use the name of a registered Node" );
504- }
505- }
506- else if (name == " BehaviorTree" )
507- {
508- if (ID.empty () && behavior_tree_count > 1 )
509- {
510- ThrowError (line_number, " The tag <BehaviorTree> must have the "
511- " attribute [ID]" );
512- }
513- if (children_count != 1 )
514- {
515- ThrowError (line_number, " The tag <BehaviorTree> must have exactly 1 "
516- " child" );
517- }
518- if (registered_nodes.count (ID) != 0 )
519- {
520- ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree> "
521- " must not use the name of a registered Node" );
473+ ThrowError (line_number, " The attribute [ID] of tag <SubTree> must not use the "
474+ " name of a registered Node" );
522475 }
523476 }
524477 else
525478 {
526- // search in the factory and the list of subtrees
527- const auto search = registered_nodes.find (name);
479+ // use ID for builtin node types, otherwise use the element name
480+ const auto lookup_name = is_builtin ? ID : name;
481+ const auto search = registered_nodes.find (lookup_name);
528482 bool found = (search != registered_nodes.end ());
529483 if (!found)
530484 {
531- ThrowError (line_number, std::string (" Node not recognized: " ) + name );
485+ ThrowError (line_number, std::string (" Node not recognized: " ) + lookup_name );
532486 }
533487
534- if (search->second == NodeType::DECORATOR)
488+ const auto node_type = search->second ;
489+ const std::string& registered_name = search->first ;
490+
491+ if (node_type == NodeType::DECORATOR)
535492 {
536493 if (children_count != 1 )
537494 {
538- ThrowError (line_number,
539- std::string ( " The node < " ) + name + " > must have exactly 1 child" );
495+ ThrowError (line_number, std::string ( " The node ' " ) + registered_name +
496+ " ' must have exactly 1 child" );
540497 }
541498 }
542- else if (search-> second == NodeType::CONTROL)
499+ else if (node_type == NodeType::CONTROL)
543500 {
544501 if (children_count == 0 )
545502 {
546- ThrowError (line_number,
547- std::string ( " The node < " ) + name + " > must have 1 or more children" );
503+ ThrowError (line_number, std::string ( " The node ' " ) + registered_name +
504+ " ' must have 1 or more children" );
548505 }
549- if (name == " ReactiveSequence" )
506+ if (registered_name == " ReactiveSequence" )
550507 {
551508 size_t async_count = 0 ;
552509 for (auto child = node->FirstChildElement (); child != nullptr ;
@@ -568,13 +525,29 @@ void VerifyXML(const std::string& xml_text,
568525 ++async_count;
569526 if (async_count > 1 )
570527 {
571- ThrowError (line_number, std::string (" A ReactiveSequence cannot have more "
572- " than one async child." ));
528+ ThrowError (line_number, std::string (" A ReactiveSequence cannot have "
529+ " more than one async child." ));
573530 }
574531 }
575532 }
576533 }
577534 }
535+ else if (node_type == NodeType::ACTION)
536+ {
537+ if (children_count != 0 )
538+ {
539+ ThrowError (line_number, std::string (" The node '" ) + registered_name +
540+ " ' must not have any child" );
541+ }
542+ }
543+ else if (node_type == NodeType::CONDITION)
544+ {
545+ if (children_count != 0 )
546+ {
547+ ThrowError (line_number, std::string (" The node '" ) + registered_name +
548+ " ' must not have any child" );
549+ }
550+ }
578551 }
579552 // recursion
580553 for (auto child = node->FirstChildElement (); child != nullptr ;
0 commit comments