@@ -429,119 +429,75 @@ void VerifyXML(const std::string& xml_text,
429
429
const std::string ID = node->Attribute (" ID" ) ? node->Attribute (" ID" ) : " " ;
430
430
const int line_number = node->GetLineNum ();
431
431
432
- if (name == " Decorator" )
432
+ // Precondition: built-in XML element types must define attribute [ID]
433
+ const bool is_builtin =
434
+ (name == " Decorator" || name == " Action" || name == " Condition" ||
435
+ name == " Control" || name == " SubTree" );
436
+ if (is_builtin && ID.empty ())
433
437
{
434
- if (children_count != 1 )
435
- {
436
- ThrowError (line_number, " The tag <Decorator> must have exactly 1 "
437
- " child" );
438
- }
439
- if (ID.empty ())
440
- {
441
- ThrowError (line_number, " The tag <Decorator> must have the "
442
- " attribute [ID]" );
443
- }
444
- }
445
- else if (name == " Action" )
446
- {
447
- if (children_count != 0 )
448
- {
449
- ThrowError (line_number, " The tag <Action> must not have any "
450
- " child" );
451
- }
452
- if (ID.empty ())
453
- {
454
- ThrowError (line_number, " The tag <Action> must have the "
455
- " attribute [ID]" );
456
- }
438
+ ThrowError (line_number,
439
+ std::string (" The tag <" ) + name + " > must have the attribute [ID]" );
457
440
}
458
- else if (name == " Condition" )
441
+
442
+ if (name == " BehaviorTree" )
459
443
{
460
- if (children_count != 0 )
461
- {
462
- ThrowError (line_number, " The tag <Condition> must not have any "
463
- " child" );
464
- }
465
- if (ID.empty ())
444
+ if (ID.empty () && behavior_tree_count > 1 )
466
445
{
467
- ThrowError (line_number, " The tag <Condition> must have the "
468
- " attribute [ID]" );
446
+ ThrowError (line_number, " The tag <BehaviorTree> must have the attribute [ID]" );
469
447
}
470
- }
471
- else if (name == " Control" )
472
- {
473
- if (children_count == 0 )
448
+ if (registered_nodes.count (ID) != 0 )
474
449
{
475
- ThrowError (line_number, " The tag <Control > must have at least 1 "
476
- " child " );
450
+ ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree > must not use "
451
+ " the name of a registered Node " );
477
452
}
478
- if (ID. empty () )
453
+ if (children_count != 1 )
479
454
{
480
- ThrowError (line_number, " The tag <Control> must have the "
481
- " attribute [ID] " );
455
+ ThrowError (line_number, " The tag <BehaviorTree> with ID ' " + ID +
456
+ " ' must have exactly 1 child " );
482
457
}
483
458
}
484
459
else if (name == " SubTree" )
485
460
{
486
461
if (children_count != 0 )
487
462
{
488
- ThrowError (line_number, " <SubTree> should not have any child" );
489
- }
490
- if (ID.empty ())
491
- {
492
- ThrowError (line_number, " The tag <SubTree> must have the "
493
- " attribute [ID]" );
463
+ ThrowError (line_number,
464
+ " <SubTree> with ID '" + ID + " ' should not have any child" );
494
465
}
495
466
if (registered_nodes.count (ID) != 0 )
496
467
{
497
- ThrowError (line_number, " The attribute [ID] of tag <SubTree> must "
498
- " not use the name of a registered Node" );
499
- }
500
- }
501
- else if (name == " BehaviorTree" )
502
- {
503
- if (ID.empty () && behavior_tree_count > 1 )
504
- {
505
- ThrowError (line_number, " The tag <BehaviorTree> must have the "
506
- " attribute [ID]" );
507
- }
508
- if (children_count != 1 )
509
- {
510
- ThrowError (line_number, " The tag <BehaviorTree> must have exactly 1 "
511
- " child" );
512
- }
513
- if (registered_nodes.count (ID) != 0 )
514
- {
515
- ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree> "
516
- " must not use the name of a registered Node" );
468
+ ThrowError (line_number, " The attribute [ID] of tag <SubTree> must not use the "
469
+ " name of a registered Node" );
517
470
}
518
471
}
519
472
else
520
473
{
521
- // search in the factory and the list of subtrees
522
- const auto search = registered_nodes.find (name);
474
+ // use ID for builtin node types, otherwise use the element name
475
+ const auto search = registered_nodes.find (is_builtin ? ID : name);
523
476
bool found = (search != registered_nodes.end ());
524
477
if (!found)
525
478
{
526
479
ThrowError (line_number, std::string (" Node not recognized: " ) + name);
527
480
}
528
481
529
- 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)
530
486
{
531
487
if (children_count != 1 )
532
488
{
533
- ThrowError (line_number,
534
- 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" );
535
491
}
536
492
}
537
- else if (search-> second == NodeType::CONTROL)
493
+ else if (node_type == NodeType::CONTROL)
538
494
{
539
495
if (children_count == 0 )
540
496
{
541
- ThrowError (line_number,
542
- 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" );
543
499
}
544
- if (name == " ReactiveSequence" )
500
+ if (registered_name == " ReactiveSequence" )
545
501
{
546
502
size_t async_count = 0 ;
547
503
for (auto child = node->FirstChildElement (); child != nullptr ;
@@ -563,13 +519,29 @@ void VerifyXML(const std::string& xml_text,
563
519
++async_count;
564
520
if (async_count > 1 )
565
521
{
566
- ThrowError (line_number, std::string (" A ReactiveSequence cannot have more "
567
- " than one async child." ));
522
+ ThrowError (line_number, std::string (" A ReactiveSequence cannot have "
523
+ " more than one async child." ));
568
524
}
569
525
}
570
526
}
571
527
}
572
528
}
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
+ }
573
545
}
574
546
// recursion
575
547
for (auto child = node->FirstChildElement (); child != nullptr ;
0 commit comments