Как читать вложенный xml с помощью rapidxml

Я пытаюсь использовать 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 может иметь очень большое количество вентилей, базовых событий, параметров и т. д., и я не думаю, что я может принимать любой конкретный порядок.


person John Schroeder    schedule 28.12.2012    source источник


Ответы (3)


node->next_sibling() возвращает вам следующий узел на том же уровне в XML-документе. Если вы хотите войти во внутренние узлы 'node', используйте first_node():

xml_node<>* nodeInternal = node->first_node();
person Evgeny Sobolev    schedule 26.02.2014

У каждого узла есть функция first_node(), поэтому внутри if, где вы определяете имя узла, вы можете выполнить еще один цикл, который начинается с xml_node<>* child = node->first_node() и продолжается с child = child->next_sibling().

person Tom Panning    schedule 28.12.2012

Спасибо за чаевые. После некоторых экспериментов я придумал следующую вспомогательную функцию для чтения «ворот». Условные операторы вложены довольно глубоко, отсюда и помощник. Работает! Еще раз, спасибо за помощь!

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();
        }
    }
} 
}  
person John Schroeder    schedule 30.12.2012
comment
P.S. Я здесь совсем новичок. Читая этот пост, неясно, является ли мой пост результатом помощи Тома Пэннинга. Но это так, спасибо - person John Schroeder; 30.12.2012