@@ -429,125 +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 (ID.empty ())
435
- {
436
- ThrowError (line_number, " The tag <Decorator> must have the "
437
- " attribute [ID]" );
438
- }
439
- if (children_count != 1 )
440
- {
441
- ThrowError (line_number, " The tag <Decorator> with ID '" + ID +
442
- " ' must have exactly 1 "
443
- " child" );
444
- }
445
- }
446
- else if (name == " Action" )
447
- {
448
- if (ID.empty ())
449
- {
450
- ThrowError (line_number, " The tag <Action> must have the "
451
- " attribute [ID]" );
452
- }
453
- if (children_count != 0 )
454
- {
455
- ThrowError (line_number, " The tag <Action> with ID '" + ID +
456
- " ' must not have any "
457
- " child" );
458
- }
438
+ ThrowError (line_number,
439
+ std::string (" The tag <" ) + name + " > must have the attribute [ID]" );
459
440
}
460
- else if (name == " Condition" )
441
+
442
+ if (name == " BehaviorTree" )
461
443
{
462
- if (ID.empty ())
463
- {
464
- ThrowError (line_number, " The tag <Condition> must have the "
465
- " attribute [ID]" );
466
- }
467
- if (children_count != 0 )
444
+ if (ID.empty () && behavior_tree_count > 1 )
468
445
{
469
- ThrowError (line_number, " The tag <Condition> with ID '" + ID +
470
- " ' must not have any "
471
- " child" );
446
+ ThrowError (line_number, " The tag <BehaviorTree> must have the attribute [ID]" );
472
447
}
473
- }
474
- else if (name == " Control" )
475
- {
476
- if (ID.empty ())
448
+ if (registered_nodes.count (ID) != 0 )
477
449
{
478
- ThrowError (line_number, " The tag <Control > must have the "
479
- " attribute [ID] " );
450
+ ThrowError (line_number, " The attribute [ID] of tag <BehaviorTree > must not use "
451
+ " the name of a registered Node " );
480
452
}
481
- if (children_count == 0 )
453
+ if (children_count != 1 )
482
454
{
483
- ThrowError (line_number, " The tag <Control> with ID '" + ID +
484
- " ' must have at least 1 "
485
- " child" );
455
+ ThrowError (line_number, " The tag <BehaviorTree> with ID '" + ID +
456
+ " ' must have exactly 1 child" );
486
457
}
487
458
}
488
459
else if (name == " SubTree" )
489
460
{
490
- if (ID.empty ())
491
- {
492
- ThrowError (line_number, " The tag <SubTree> must have the "
493
- " attribute [ID]" );
494
- }
495
461
if (children_count != 0 )
496
462
{
497
463
ThrowError (line_number,
498
464
" <SubTree> with ID '" + ID + " ' should not have any child" );
499
465
}
500
466
if (registered_nodes.count (ID) != 0 )
501
467
{
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 (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" );
517
- }
518
- if (children_count != 1 )
519
- {
520
- ThrowError (line_number, " The tag <BehaviorTree> with ID '" + ID +
521
- " ' must have exactly 1 "
522
- " child" );
468
+ ThrowError (line_number, " The attribute [ID] of tag <SubTree> must not use the "
469
+ " name of a registered Node" );
523
470
}
524
471
}
525
472
else
526
473
{
527
- // search in the factory and the list of subtrees
528
- 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);
529
476
bool found = (search != registered_nodes.end ());
530
477
if (!found)
531
478
{
532
479
ThrowError (line_number, std::string (" Node not recognized: " ) + name);
533
480
}
534
481
535
- 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)
536
486
{
537
487
if (children_count != 1 )
538
488
{
539
- ThrowError (line_number, std::string (" The node < " ) + name + " > with ID ' " + ID +
489
+ ThrowError (line_number, std::string (" The node ' " ) + registered_name +
540
490
" ' must have exactly 1 child" );
541
491
}
542
492
}
543
- else if (search-> second == NodeType::CONTROL)
493
+ else if (node_type == NodeType::CONTROL)
544
494
{
545
495
if (children_count == 0 )
546
496
{
547
- ThrowError (line_number, std::string (" The node < " ) + name + " > with ID ' " + ID +
497
+ ThrowError (line_number, std::string (" The node ' " ) + registered_name +
548
498
" ' must have 1 or more children" );
549
499
}
550
- if (name == " ReactiveSequence" )
500
+ if (registered_name == " ReactiveSequence" )
551
501
{
552
502
size_t async_count = 0 ;
553
503
for (auto child = node->FirstChildElement (); child != nullptr ;
@@ -569,14 +519,29 @@ void VerifyXML(const std::string& xml_text,
569
519
++async_count;
570
520
if (async_count > 1 )
571
521
{
572
- ThrowError (line_number, std::string (" A ReactiveSequence with ID '" + ID +
573
- " ' cannot have more "
574
- " than one async child." ));
522
+ ThrowError (line_number, std::string (" A ReactiveSequence cannot have "
523
+ " more than one async child." ));
575
524
}
576
525
}
577
526
}
578
527
}
579
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
+ }
580
545
}
581
546
// recursion
582
547
for (auto child = node->FirstChildElement (); child != nullptr ;
0 commit comments