@@ -434,119 +434,76 @@ void VerifyXML(const std::string& xml_text,
434
434
const std::string ID = node->Attribute (" ID" ) ? node->Attribute (" ID" ) : " " ;
435
435
const int line_number = node->GetLineNum ();
436
436
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 ())
438
442
{
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]" );
462
445
}
463
- else if (name == " Condition" )
446
+
447
+ if (name == " BehaviorTree" )
464
448
{
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 )
471
450
{
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]" );
474
452
}
475
- }
476
- else if (name == " Control" )
477
- {
478
- if (children_count == 0 )
453
+ if (registered_nodes.count (ID) != 0 )
479
454
{
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 " );
482
457
}
483
- if (ID. empty () )
458
+ if (children_count != 1 )
484
459
{
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 " );
487
462
}
488
463
}
489
464
else if (name == " SubTree" )
490
465
{
491
466
if (children_count != 0 )
492
467
{
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" );
499
470
}
500
471
if (registered_nodes.count (ID) != 0 )
501
472
{
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" );
522
475
}
523
476
}
524
477
else
525
478
{
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);
528
482
bool found = (search != registered_nodes.end ());
529
483
if (!found)
530
484
{
531
- ThrowError (line_number, std::string (" Node not recognized: " ) + name );
485
+ ThrowError (line_number, std::string (" Node not recognized: " ) + lookup_name );
532
486
}
533
487
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)
535
492
{
536
493
if (children_count != 1 )
537
494
{
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" );
540
497
}
541
498
}
542
- else if (search-> second == NodeType::CONTROL)
499
+ else if (node_type == NodeType::CONTROL)
543
500
{
544
501
if (children_count == 0 )
545
502
{
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" );
548
505
}
549
- if (name == " ReactiveSequence" )
506
+ if (registered_name == " ReactiveSequence" )
550
507
{
551
508
size_t async_count = 0 ;
552
509
for (auto child = node->FirstChildElement (); child != nullptr ;
@@ -568,13 +525,29 @@ void VerifyXML(const std::string& xml_text,
568
525
++async_count;
569
526
if (async_count > 1 )
570
527
{
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." ));
573
530
}
574
531
}
575
532
}
576
533
}
577
534
}
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
+ }
578
551
}
579
552
// recursion
580
553
for (auto child = node->FirstChildElement (); child != nullptr ;
0 commit comments