| 1471 | } |
| 1472 | |
| 1473 | std::string writeTreeXSD(const BehaviorTreeFactory& factory) |
| 1474 | { |
| 1475 | // There are 2 forms of representation for a node: |
| 1476 | // compact: <Sequence .../> and explicit: <Control ID="Sequence" ... /> |
| 1477 | // Only the compact form is supported because the explicit form doesn't |
| 1478 | // make sense with XSD since we would need to allow any attribute. |
| 1479 | // Prepare the data |
| 1480 | |
| 1481 | std::map<std::string, const TreeNodeManifest*> ordered_models; |
| 1482 | for(const auto& [registration_id, model] : factory.manifests()) |
| 1483 | { |
| 1484 | ordered_models.insert({ registration_id, &model }); |
| 1485 | } |
| 1486 | |
| 1487 | XMLDocument doc; |
| 1488 | |
| 1489 | // Add the XML declaration |
| 1490 | XMLDeclaration* declaration = doc.NewDeclaration("xml version=\"1.0\" " |
| 1491 | "encoding=\"UTF-8\""); |
| 1492 | doc.InsertFirstChild(declaration); |
| 1493 | |
| 1494 | // Create the root element with namespace and attributes |
| 1495 | // To validate a BT XML file with `schema.xsd` in the same directory: |
| 1496 | // <root BTCPP_format="4" main_tree_to_execute="MainTree" |
| 1497 | // xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| 1498 | // xsi:noNamespaceSchemaLocation="schema.xsd"> |
| 1499 | XMLElement* schema_element = doc.NewElement("xs:schema"); |
| 1500 | schema_element->SetAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema"); |
| 1501 | schema_element->SetAttribute("elementFormDefault", "qualified"); |
| 1502 | doc.InsertEndChild(schema_element); |
| 1503 | |
| 1504 | auto parse_and_insert = [&doc](XMLElement* parent_elem, const char* str) { |
| 1505 | XMLDocument tmp_doc; |
| 1506 | tmp_doc.Parse(str); |
| 1507 | if(tmp_doc.Error()) |
| 1508 | { |
| 1509 | std::cerr << "Internal error parsing existing XML: " << tmp_doc.ErrorStr() |
| 1510 | << std::endl; |
| 1511 | return; |
| 1512 | } |
| 1513 | for(auto child = tmp_doc.FirstChildElement(); child != nullptr; |
| 1514 | child = child->NextSiblingElement()) |
| 1515 | { |
| 1516 | parent_elem->InsertEndChild(child->DeepClone(&doc)); |
| 1517 | } |
| 1518 | }; |
| 1519 | |
| 1520 | // Common elements. |
| 1521 | XMLComment* comment = doc.NewComment("Define the common elements"); |
| 1522 | schema_element->InsertEndChild(comment); |
| 1523 | |
| 1524 | // TODO: add <xs:whiteSpace value="preserve"/> for `inputPortType` and `outputPortType`. |
| 1525 | parse_and_insert(schema_element, R"( |
| 1526 | <xs:simpleType name="blackboardType"> |
| 1527 | <xs:restriction base="xs:string"> |
| 1528 | <xs:pattern value="\{.*\}"/> |
| 1529 | </xs:restriction> |
| 1530 | </xs:simpleType> |
nothing calls this directly
no test coverage detected