Я пытаюсь использовать RapidXML для анализа содержимого XML, которое выглядит следующим образом:
<?xml version="1.0" ?>
<!DOCTYPE open-psa>
<open-psa>
<define-gate name="top" >
<or>
<gate name="g1" />
<gate name="g2" />
</or>
</define-gate>
<define-basic-event name="e1">
<exponential>
<parameter name="lambda1" />
<mission-time />
</exponential>
</define-basic-event>
<define-parameter name="lambda1">
<lognormal-deviate>
<float value="2.0e-5" />
<float value="3" />
<float value="0.95" />
</lognormal-deviate>
</define-parameter>
</open-psa>
Я был в состоянии получить доступ ко всем прямым детям в open-psa, используя следующий код
cout << "Importing fault tree...\n" ;
xml_document<> doc;
xml_node<> * root_node;
char* node_name;
// Read the xml file into a buffer
ifstream theFile ("SmallTree.xml");
vector<char> buffer((istreambuf_iterator<char>(theFile)),
istreambuf_iterator<char>());
buffer.push_back('\0');
// Parse the buffer
doc.parse<0>(&buffer[0]);
// Find the root node
root_node = doc.first_node("open-psa");
// Iterate over all child nodes
for (xml_node<> * node = root_node->first_node(); node; node = node->next_sibling())
{
node_name = node->name();
if (strcmp(node_name, "define-gate" ) == 0)
{
cout << node->name() << ", ";
cout << node->first_attribute("name")->value() << endl;
}
else if (strcmp(node_name, "define-basic-event" ) == 0)
{
cout << node->name() << ", ";
cout << node->first_attribute("name")->value() << endl;
}
else if (strcmp(node_name, "define-parameter" ) == 0)
{
cout << node->name() << ", ";
cout << node->first_attribute("name")->value() << endl;
}
}
Теперь я застрял. Как получить доступ к элементам, вложенным, скажем, в define-gate name = «top»? Как вы можете догадаться, реальный файл .xml может иметь очень большое количество элементов, основных событий, параметров и т. Д., И я не думаю, что может принять любой конкретный порядок.
Каждый узел имеет функцию first_node (), поэтому внутри if
где вы определяете имя узла, вы можете сделать еще один цикл, который начинается с xml_node<>* child = node->first_node()
и продолжается с child = child->next_sibling()
,
Спасибо за чаевые. После некоторых экспериментов я придумал следующую вспомогательную функцию для чтения «ворот». Условные операторы вложены довольно глубоко, отсюда и помощник. Работает! Еще раз, спасибо за помощь!
void readGate(xml_node<>* node)
{
//
char* gname ;
xml_node<>* gtype = node->first_node();
if (gtype != 0)
{
gname = gtype->name();
if (strcmp(gname, "and" ) == 0)
{
// found an "and" gate, read children
cout << " " << gname << endl;
xml_node<>* gin = gtype->first_node();
while (gin != 0)
{
cout << " " << gin->name() << ", ";
cout << " " << gin->first_attribute("name")->value();
cout << endl;
gin = gin->next_sibling();
}
}
else if (strcmp(gname, "or" ) == 0)
{
// found an "or" gate, read children
cout << " " << gname << endl;
xml_node<>* gin = gtype->first_node();
while(gin != 0)
{
cout << " " << gin->name() << ", ";
cout << " " << gin->first_attribute("name")->value();
cout << endl;
gin = gin->next_sibling();
}
}
}
}
node-> next_sibling () возвращает вас к следующему узлу того же уровня в документе XML. Если вы хотите войти во внутренние узлы узла, используйте first_node ():
xml_node<>* nodeInternal = node->first_node();