Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0d9d56b

Browse files
committed
make verifyXML reusable
1 parent e0c380e commit 0d9d56b

File tree

2 files changed

+60
-29
lines changed

2 files changed

+60
-29
lines changed

include/behaviortree_cpp/xml_parsing.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class XMLParser: public Parser
3434

3535
};
3636

37+
void VerifyXML(const std::string& xml_text,
38+
const std::set<std::string> &registered_nodes);
3739

3840
std::string writeTreeNodesModelXML(const BehaviorTreeFactory& factory);
3941

src/xml_parsing.cpp

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ struct XMLParser::Pimpl
4343

4444
void loadDocImpl(XMLDocument *doc);
4545

46-
void verifyXML(const XMLDocument* doc) const;
47-
4846
std::list< std::unique_ptr<XMLDocument> > opened_documents;
4947
std::unordered_map<std::string,const XMLElement*> tree_roots;
5048

@@ -166,11 +164,37 @@ void XMLParser::Pimpl::loadDocImpl(XMLDocument* doc)
166164
}
167165
tree_roots.insert( {tree_name, bt_node} );
168166
}
169-
verifyXML(doc);
167+
168+
std::set<std::string> registered_nodes;
169+
XMLPrinter printer;
170+
doc->Print(&printer);
171+
auto xml_text = std::string(printer.CStr(), size_t(printer.CStrSize() - 1));
172+
173+
for( const auto& it: factory.manifests())
174+
{
175+
registered_nodes.insert( it.first );
176+
}
177+
for( const auto& it: tree_roots)
178+
{
179+
registered_nodes.insert( it.first );
180+
}
181+
182+
VerifyXML(xml_text, registered_nodes);
170183
}
171184

172-
void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
185+
void VerifyXML(const std::string& xml_text,
186+
const std::set<std::string>& registered_nodes)
173187
{
188+
189+
XMLDocument doc;
190+
auto xml_error = doc.Parse( xml_text.c_str(), xml_text.size());
191+
if (xml_error)
192+
{
193+
char buffer[200];
194+
sprintf(buffer, "Error parsing the XML: %s", doc.ErrorName() );
195+
throw RuntimeError( buffer );
196+
}
197+
174198
//-------- Helper functions (lambdas) -----------------
175199
auto StrEqual = [](const char* str1, const char* str2) -> bool {
176200
return strcmp(str1, str2) == 0;
@@ -193,7 +217,7 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
193217
};
194218
//-----------------------------
195219

196-
const XMLElement* xml_root = doc->RootElement();
220+
const XMLElement* xml_root = doc.RootElement();
197221

198222
if (!xml_root || !StrEqual(xml_root->Name(), "root"))
199223
{
@@ -205,8 +229,8 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
205229

206230
if (meta_sibling)
207231
{
208-
ThrowError(meta_sibling->GetLineNum(), " Only a single node <TreeNodesModel> is "
209-
"supported");
232+
ThrowError(meta_sibling->GetLineNum(),
233+
" Only a single node <TreeNodesModel> is supported");
210234
}
211235
if (meta_root)
212236
{
@@ -222,8 +246,8 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
222246
const char* ID = node->Attribute("ID");
223247
if (!ID)
224248
{
225-
ThrowError(node->GetLineNum(), "Error at line %d: -> The attribute [ID] is "
226-
"mandatory");
249+
ThrowError(node->GetLineNum(),
250+
"Error at line %d: -> The attribute [ID] is mandatory");
227251
}
228252
}
229253
}
@@ -240,43 +264,48 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
240264
{
241265
if (children_count != 1)
242266
{
243-
ThrowError(node->GetLineNum(), "The node <Decorator> must have exactly 1 child");
267+
ThrowError(node->GetLineNum(),
268+
"The node <Decorator> must have exactly 1 child");
244269
}
245270
if (!node->Attribute("ID"))
246271
{
247-
ThrowError(node->GetLineNum(), "The node <Decorator> must have the attribute "
248-
"[ID]");
272+
ThrowError(node->GetLineNum(),
273+
"The node <Decorator> must have the attribute [ID]");
249274
}
250275
}
251276
else if (StrEqual(name, "Action"))
252277
{
253278
if (children_count != 0)
254279
{
255-
ThrowError(node->GetLineNum(), "The node <Action> must not have any child");
280+
ThrowError(node->GetLineNum(),
281+
"The node <Action> must not have any child");
256282
}
257283
if (!node->Attribute("ID"))
258284
{
259-
ThrowError(node->GetLineNum(), "The node <Action> must have the attribute [ID]");
285+
ThrowError(node->GetLineNum(),
286+
"The node <Action> must have the attribute [ID]");
260287
}
261288
}
262289
else if (StrEqual(name, "Condition"))
263290
{
264291
if (children_count != 0)
265292
{
266-
ThrowError(node->GetLineNum(), "The node <Condition> must not have any child");
293+
ThrowError(node->GetLineNum(),
294+
"The node <Condition> must not have any child");
267295
}
268296
if (!node->Attribute("ID"))
269297
{
270-
ThrowError(node->GetLineNum(), "The node <Condition> must have the attribute "
271-
"[ID]");
298+
ThrowError(node->GetLineNum(),
299+
"The node <Condition> must have the attribute [ID]");
272300
}
273301
}
274302
else if (StrEqual(name, "Sequence") || StrEqual(name, "SequenceStar") ||
275303
StrEqual(name, "Fallback") || StrEqual(name, "FallbackStar"))
276304
{
277305
if (children_count == 0)
278306
{
279-
ThrowError(node->GetLineNum(), "A Control node must have at least 1 child");
307+
ThrowError(node->GetLineNum(),
308+
"A Control node must have at least 1 child");
280309
}
281310
}
282311
else if (StrEqual(name, "SubTree"))
@@ -286,25 +315,25 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
286315
{
287316
if( StrEqual(child->Name(), "remap") == false)
288317
{
289-
ThrowError(node->GetLineNum(), "<SubTree> accept only childs of type <remap>");
318+
ThrowError(node->GetLineNum(),
319+
"<SubTree> accept only childs of type <remap>");
290320
}
291321
}
292322

293323
if (!node->Attribute("ID"))
294324
{
295-
ThrowError(node->GetLineNum(), "The node <SubTree> must have the attribute [ID]");
325+
ThrowError(node->GetLineNum(),
326+
"The node <SubTree> must have the attribute [ID]");
296327
}
297328
}
298329
else
299330
{
300331
// search in the factory and the list of subtrees
301-
const auto& manifests = factory.manifests();
302-
303-
bool found = ( manifests.find(name) != manifests.end() ||
304-
tree_roots.find(name) != tree_roots.end() );
332+
bool found = ( registered_nodes.find(name) != registered_nodes.end() );
305333
if (!found)
306334
{
307-
ThrowError(node->GetLineNum(), std::string("Node not recognized: ") + name);
335+
ThrowError(node->GetLineNum(),
336+
std::string("Node not recognized: ") + name);
308337
}
309338
}
310339
//recursion
@@ -331,7 +360,8 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
331360
}
332361
if (ChildrenCount(bt_root) != 1)
333362
{
334-
ThrowError(bt_root->GetLineNum(), "The node <BehaviorTree> must have exactly 1 child");
363+
ThrowError(bt_root->GetLineNum(),
364+
"The node <BehaviorTree> must have exactly 1 child");
335365
}
336366
else
337367
{
@@ -351,9 +381,8 @@ void XMLParser::Pimpl::verifyXML(const XMLDocument* doc) const
351381
{
352382
if (tree_count != 1)
353383
{
354-
throw RuntimeError(
355-
"If you don't specify the attribute [main_tree_to_execute], "
356-
"Your file must contain a single BehaviorTree");
384+
throw RuntimeError("If you don't specify the attribute [main_tree_to_execute], "
385+
"Your file must contain a single BehaviorTree");
357386
}
358387
}
359388
}

0 commit comments

Comments
 (0)