RapidXML Получить доступ к отдельному значению атрибута, используя предыдущее значение атрибута?

Я использую RapidXML и C++ в VS2012 на ПК. Я уже проанализировал файл XML, но теперь хочу распечатать значения атрибутов по отдельности. Обычно я могу сделать это, используя приведенный ниже код. Однако этот метод должен знать имя узла и имя атрибута. Это проблема, потому что у меня есть несколько узлов с одним и тем же именем и несколько атрибутов с одним и тем же именем. Мой вопрос заключается в следующем: как мне получить одно значение атрибута, если ни имя узла, ни имя атрибута не являются уникальными?

Код, который я использую, когда у меня есть уникальное имя узла и имя атрибута:

xml_node<> *node0 = doc.first_node("NodeName"); //define the individual node you want to access
xml_attribute<> *attr = node0->first_attribute("price"); //define the individual attribute that you want to access
cout << "Node NodeName has attribute " << attr->name() << " ";
cout << "with value " << attr->value() << "\n";

Мой тестовый файл XML:

<catalog>
  <book>
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <price>44.95</price>
  </book>
  <book>
  <author>Ralls, Kim</author>
  <title>Midnight Rain</title>
  <price>5.95</price>
  </book>
</catalog>

В этом конкретном примере, как я могу получить значение атрибута цены для второй книги? Могу ли я ввести значение атрибута заголовка «Полуночный дождь» и каким-то образом использовать его для получения следующего значения?


person Ty Roderick    schedule 16.07.2013    source источник
comment
price - это не атрибут, это узел. Атрибуты XML выглядят как <book price="5.95">   -  person Roddy    schedule 14.08.2013


Ответы (2)


Вы можете использовать функцию-член next_sibling(const char *) для перебора одноуровневых узлов, пока не найдете узел с правильным значением атрибута. Я не тестировал следующий код, но он должен дать представление о том, что вам нужно сделать:

typedef rapidxml::xml_node<>      node_type;
typedef rapidxml::xml_attribute<> attribute_type;

/// find a child of a specific type for which the given attribute has 
/// the given value...
node_type *find_child( 
    node_type *parent, 
    const std::string &type, 
    const std::string &attribute, 
    const std::string &value)
{
    node_type *node = parent->first_node( type.c_str());
    while (node)
    {
        attribute_type *attr = node->first_attribute( attribute.c_str());
        if ( attr && value == attr->value()) return node;
        node = node->next_sibling( type.c_str());
    }
    return node;
}

Затем вы можете найти вторую книгу, позвонив по телефону:

node_type *midnight = find_child( doc, "book", "title", "Midnight Rain");

Получить цену этой книги должно быть легко.

В общем, когда имеешь дело с rapidxml, я склонен создавать много таких маленьких вспомогательных функций. Я считаю, что они облегчают чтение моего кода в отсутствие функций xpath...

person dhavenith    schedule 16.07.2013
comment
Ваш код не работает, потому что node_type является неоднозначным символом... Я также не совсем понимаю, что пытается сделать node_type. Как вы думаете, вы могли бы немного больше прокомментировать свой код или, возможно, даже протестировать его самостоятельно? Прошу прощения, если эта проблема кажется очевидной, я впервые работаю с rapidxml. - person Ty Roderick; 17.07.2013
comment
по-видимому, в вашей среде у вас уже есть символ 'node_type'. Вы можете заменить node_type в приведенном выше коде на xml_node‹›. Обратите внимание, что это только иллюстрация. Ключевое сообщение: используйте next_sibling(const char *), как в примере выше. - person dhavenith; 17.07.2013

Когда вы говорите несколько узлов с одним и тем же именем и несколько атрибутов с одним и тем же именем, вы имеете в виду; несколько узлов и несколько атрибутов? Если это так, то я думаю, что вы пытаетесь передать несколько сообщений xml. Однако вы должны иметь возможность сначала успешно передать первое сообщение xml, а затем второе сообщение. Вы не включили весь код, я бы сначала проверил, действительно ли метод doc.first_node создает xml_node.

person Juniar    schedule 16.07.2013