| 161 | |
| 162 | |
| 163 | template <typename XE> inline element_path_t<XE> element_path_from_xpath (XE * root, const std::string & xpath) |
| 164 | { |
| 165 | if (!root) |
| 166 | throw XmlException ("null element"s); |
| 167 | |
| 168 | element_path_t<XE> ep; |
| 169 | |
| 170 | // split the path |
| 171 | size_t start = 0; |
| 172 | size_t pos; |
| 173 | // set element at head of selection branch |
| 174 | // if path starts with '/' then it is relative to document, otherwise relative to element passed in |
| 175 | // first element in selection branch is the root and only children of the root are considered |
| 176 | // for document-based paths, this works because there can only be one document element |
| 177 | if (!xpath.empty() && xpath[0] == '/') |
| 178 | { |
| 179 | // document is not an element so needs special handling |
| 180 | // advance to the actual document element |
| 181 | // note that document element must still appear in path, so we have to step over it |
| 182 | ++start; |
| 183 | if ((pos = xpath .find ('/', start)) != std::string::npos) |
| 184 | { |
| 185 | auto filter = ElementProperties (xpath .substr (start, pos - start)); |
| 186 | auto element = root -> GetDocument() -> RootElement(); |
| 187 | if (element && !filter .Name() .empty()) |
| 188 | { |
| 189 | if (filter .Name() != std::string (element -> Name())) |
| 190 | throw XmlException ("document element name mismatch"s); |
| 191 | } |
| 192 | ep .emplace_back (std::make_pair (filter, element)); |
| 193 | start = pos + 1; |
| 194 | } |
| 195 | } |
| 196 | else |
| 197 | ep .emplace_back (std::make_pair (ElementProperties (root -> Name()), root)); |
| 198 | |
| 199 | // continue with other elements along path |
| 200 | while ((pos = xpath .find ('/', start)) != std::string::npos) |
| 201 | { |
| 202 | ep .emplace_back (std::make_pair (ElementProperties (xpath .substr (start, pos - start)), nullptr)); |
| 203 | start = pos + 1; |
| 204 | } |
| 205 | // and the final element |
| 206 | ep .emplace_back (std::make_pair (ElementProperties (xpath .substr (start, pos - start)), nullptr)); |
| 207 | |
| 208 | return ep; |
| 209 | } |
| 210 | |
| 211 | |
| 212 | template <typename XE> inline element_path_t<XE> element_path_from_element (XE * e) |
no test coverage detected