append / prepend element common method for all append / prepend element insertions todo: consider using std::initializer_list for attributes parameter
| 478 | // common method for all append / prepend element insertions |
| 479 | // todo: consider using std::initializer_list<AttributeNameValue> for attributes parameter |
| 480 | inline XMLElement * append_element (XMLElement * parent, const std::string & xpath, const attribute_list_t & attributes, const std::string & text, bool addAtBack) |
| 481 | { |
| 482 | XMLElement * element {nullptr}; |
| 483 | bool inserted {false}; |
| 484 | |
| 485 | element_path_t<XMLElement> branch {element_path_from_xpath (parent, xpath)}; |
| 486 | // add all the elements to create new branch |
| 487 | // first element in branch is the parent, so skip |
| 488 | for (auto be = ++branch .begin(); be != branch .end(); ++be) |
| 489 | { |
| 490 | element = parent -> GetDocument() -> NewElement (be -> first .Name() .c_str()); |
| 491 | if (!element) |
| 492 | break; |
| 493 | // and set element attributes from XPath data |
| 494 | be -> first .Update (element); |
| 495 | be -> second = element; |
| 496 | // insert new element into hierarchy |
| 497 | auto last = parent -> LastChildElement(); |
| 498 | if (addAtBack && last) |
| 499 | // XMLElement::InsertEndChild puts new element after *all* nodes, including text, which looks odd |
| 500 | // therefore, add new element immediately after current last element when present, otherwise first |
| 501 | inserted = parent -> InsertAfterChild (last, element) != nullptr; |
| 502 | else |
| 503 | inserted = parent -> InsertFirstChild (element) != nullptr; |
| 504 | |
| 505 | parent = element; // move along branch as it's built |
| 506 | } |
| 507 | if (inserted) |
| 508 | { |
| 509 | // set the attributes and text for final element from arguments |
| 510 | for (auto const & attr : attributes) |
| 511 | element -> SetAttribute (attr .Name() .c_str(), attr .Value() .c_str()); |
| 512 | if (!text .empty()) |
| 513 | element -> SetText (text .c_str()); |
| 514 | return element; |
| 515 | } |
| 516 | else |
| 517 | { |
| 518 | // failed, delete any elements we created |
| 519 | for (auto be = ++branch .begin(); be != branch .end(); ++be) |
| 520 | parent -> GetDocument() -> DeleteNode (be -> second); |
| 521 | throw XmlException ("unable to append element"s); |
| 522 | } |
| 523 | // always returns valid XMLElement on success, failures are exceptions |
| 524 | } |
| 525 | |
| 526 | |
| 527 | // append family |
no test coverage detected