@@ -428,119 +428,76 @@ void VerifyXML(const std::string& xml_text,
428428 const std::string ID = node->Attribute (" ID" ) ? node->Attribute (" ID" ) : " " ;
429429 const int line_number = node->GetLineNum ();
430430
431- if (name == " Decorator" )
431+ // Precondition: built-in XML element types must define attribute [ID]
432+ const bool is_builtin =
433+ (name == " Decorator" || name == " Action" || name == " Condition" ||
434+ name == " Control" || name == " SubTree" );
435+ if (is_builtin && ID.empty ())
432436 {
433- if (children_count != 1 )
434- {
435- ThrowError (line_number, " The tag <Decorator> must have exactly 1 "
436- " child" );
437- }
438- if (ID.empty ())
439- {
440- ThrowError (line_number, " The tag <Decorator> must have the "
441- " attribute [ID]" );
442- }
443- }
444- else if (name == " Action" )
445- {
446- if (children_count != 0 )
447- {
448- ThrowError (line_number, " The tag <Action> must not have any "
449- " child" );
450- }
451- if (ID.empty ())
452- {
453- ThrowError (line_number, " The tag <Action> must have the "
454- " attribute [ID]" );
455- }
437+ ThrowError (line_number,
438+ std::string (" The tag <" ) + name + " > must have the attribute [ID]" );
456439 }
457- else if (name == " Condition" )
440+
441+ if (name == " BehaviorTree" )
458442 {
459- if (children_count != 0 )
460- {
461- ThrowError (line_number, " The tag <Condition> must not have any "
462- " child" );
463- }
464- if (ID.empty ())
443+ if (ID.empty () && behavior_tree_count > 1 )
465444 {
466- ThrowError (line_number, " The tag <Condition> must have the "
467- " attribute [ID]" );
445+ ThrowError (line_number, " The tag <BehaviorTree> must have the attribute [ID]" );
468446 }
469- }
470- else if (name == " Control" )
471- {
472- if (children_count == 0 )
447+ if (registered_nodes.count (ID) != 0 )
473448 {
474- ThrowError (line_number, " The tag <Control > must have at least 1 "
475- " child " );
449+ ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree > must not use "
450+ " the name of a registered Node " );
476451 }
477- if (ID. empty () )
452+ if (children_count != 1 )
478453 {
479- ThrowError (line_number, " The tag <Control> must have the "
480- " attribute [ID] " );
454+ ThrowError (line_number, " The tag <BehaviorTree> with ID ' " + ID +
455+ " ' must have exactly 1 child " );
481456 }
482457 }
483458 else if (name == " SubTree" )
484459 {
485460 if (children_count != 0 )
486461 {
487- ThrowError (line_number, " <SubTree> should not have any child" );
488- }
489- if (ID.empty ())
490- {
491- ThrowError (line_number, " The tag <SubTree> must have the "
492- " attribute [ID]" );
462+ ThrowError (line_number,
463+ " <SubTree> with ID '" + ID + " ' should not have any child" );
493464 }
494465 if (registered_nodes.count (ID) != 0 )
495466 {
496- ThrowError (line_number, " The attribute [ID] of tag <SubTree> must "
497- " not use the name of a registered Node" );
498- }
499- }
500- else if (name == " BehaviorTree" )
501- {
502- if (ID.empty () && behavior_tree_count > 1 )
503- {
504- ThrowError (line_number, " The tag <BehaviorTree> must have the "
505- " attribute [ID]" );
506- }
507- if (children_count != 1 )
508- {
509- ThrowError (line_number, " The tag <BehaviorTree> must have exactly 1 "
510- " child" );
511- }
512- if (registered_nodes.count (ID) != 0 )
513- {
514- ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree> "
515- " must not use the name of a registered Node" );
467+ ThrowError (line_number, " The attribute [ID] of tag <SubTree> must not use the "
468+ " name of a registered Node" );
516469 }
517470 }
518471 else
519472 {
520- // search in the factory and the list of subtrees
521- const auto search = registered_nodes.find (name);
473+ // use ID for builtin node types, otherwise use the element name
474+ const auto lookup_name = is_builtin ? ID : name;
475+ const auto search = registered_nodes.find (lookup_name);
522476 bool found = (search != registered_nodes.end ());
523477 if (!found)
524478 {
525- ThrowError (line_number, std::string (" Node not recognized: " ) + name );
479+ ThrowError (line_number, std::string (" Node not recognized: " ) + lookup_name );
526480 }
527481
528- if (search->second == NodeType::DECORATOR)
482+ const auto node_type = search->second ;
483+ const std::string& registered_name = search->first ;
484+
485+ if (node_type == NodeType::DECORATOR)
529486 {
530487 if (children_count != 1 )
531488 {
532- ThrowError (line_number,
533- std::string ( " The node < " ) + name + " > must have exactly 1 child" );
489+ ThrowError (line_number, std::string ( " The node ' " ) + registered_name +
490+ " ' must have exactly 1 child" );
534491 }
535492 }
536- else if (search-> second == NodeType::CONTROL)
493+ else if (node_type == NodeType::CONTROL)
537494 {
538495 if (children_count == 0 )
539496 {
540- ThrowError (line_number,
541- std::string ( " The node < " ) + name + " > must have 1 or more children" );
497+ ThrowError (line_number, std::string ( " The node ' " ) + registered_name +
498+ " ' must have 1 or more children" );
542499 }
543- if (name == " ReactiveSequence" )
500+ if (registered_name == " ReactiveSequence" )
544501 {
545502 size_t async_count = 0 ;
546503 for (auto child = node->FirstChildElement (); child != nullptr ;
@@ -562,13 +519,29 @@ void VerifyXML(const std::string& xml_text,
562519 ++async_count;
563520 if (async_count > 1 )
564521 {
565- ThrowError (line_number, std::string (" A ReactiveSequence cannot have more "
566- " than one async child." ));
522+ ThrowError (line_number, std::string (" A ReactiveSequence cannot have "
523+ " more than one async child." ));
567524 }
568525 }
569526 }
570527 }
571528 }
529+ else if (node_type == NodeType::ACTION)
530+ {
531+ if (children_count != 0 )
532+ {
533+ ThrowError (line_number, std::string (" The node '" ) + registered_name +
534+ " ' must not have any child" );
535+ }
536+ }
537+ else if (node_type == NodeType::CONDITION)
538+ {
539+ if (children_count != 0 )
540+ {
541+ ThrowError (line_number, std::string (" The node '" ) + registered_name +
542+ " ' must not have any child" );
543+ }
544+ }
572545 }
573546 // recursion
574547 for (auto child = node->FirstChildElement (); child != nullptr ;
0 commit comments