MUSX Document Model
Loading...
Searching...
No Matches
RapidXmlImpl.h
1/*
2 * Copyright (C) 2025, Robert Patterson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22#pragma once
23
24#ifdef MUSX_USE_RAPIDXML
25
26#include <string>
27#include <memory>
28#include <vector>
29#include <exception>
30
31#include "rapidxml.hpp"
32#include "XmlInterface.h"
33
34namespace musx {
35namespace xml {
36
45namespace rapidxml {
46
51{
52 ::rapidxml::xml_attribute<>* m_attribute;
53
54public:
58 explicit Attribute(::rapidxml::xml_attribute<>* attr) : m_attribute(attr) {}
60 std::string getName() const override { return m_attribute->name(); }
61 std::string getValue() const override { return m_attribute->value(); }
63 std::shared_ptr<IXmlAttribute> nextAttribute() const override {
64 ::rapidxml::xml_attribute<>* next = m_attribute->next_attribute();
65 return next ? std::make_shared<Attribute>(next) : nullptr;
66 }
67};
68
73{
74 ::rapidxml::xml_node<>* m_element;
75
76 static const char* tagPtr(const std::string& tagName) {
77 return tagName.empty() ? nullptr : tagName.c_str();
78 }
79
80public:
84 explicit Element(::rapidxml::xml_node<>* elem) : m_element(elem) {}
86 std::string getTagName() const override { return m_element->name(); }
88 std::string getText() const override {
89 return m_element->value() ? m_element->value() : "";
90 }
92 std::shared_ptr<IXmlAttribute> getFirstAttribute() const override {
93 ::rapidxml::xml_attribute<>* attr = m_element->first_attribute();
94 return attr ? std::make_shared<Attribute>(attr) : nullptr;
95 }
97 std::shared_ptr<IXmlAttribute> findAttribute(const std::string& tagName) const override {
98 ::rapidxml::xml_attribute<>* attr = m_element->first_attribute(tagName.c_str());
99 return attr ? std::make_shared<Attribute>(attr) : nullptr;
100 }
102 std::shared_ptr<IXmlElement> getFirstChildElement(const std::string& tagName = {}) const override {
103 ::rapidxml::xml_node<>* child = m_element->first_node(tagPtr(tagName));
104 return child ? std::make_shared<Element>(child) : nullptr;
105 }
107 std::shared_ptr<IXmlElement> getNextSibling(const std::string& tagName = {}) const override {
108 ::rapidxml::xml_node<>* sibling = m_element->next_sibling(tagPtr(tagName));
109 return sibling ? std::make_shared<Element>(sibling) : nullptr;
110 }
112 std::shared_ptr<IXmlElement> getPreviousSibling(const std::string& tagName = {}) const override {
113 // rapidxml does not directly support previous sibling, we need to iterate from the parent.
114 if (!m_element->parent()) return nullptr;
115
116 ::rapidxml::xml_node<>* prev = nullptr;
117 for (::rapidxml::xml_node<>* sibling = m_element->parent()->first_node(); sibling; sibling = sibling->next_sibling()) {
118 if (sibling == m_element) break;
119 if (tagName.empty() || sibling->name() == tagName) prev = sibling;
120 }
121 return prev ? std::make_shared<Element>(prev) : nullptr;
122 }
124 std::shared_ptr<IXmlElement> getParent() const override {
125 ::rapidxml::xml_node<>* parent = m_element->parent();
126 return parent && parent->type() == ::rapidxml::node_element ? std::make_shared<Element>(parent) : nullptr;
127 }
128};
129
134{
135 ::rapidxml::xml_document<> m_document;
136 std::vector<char> m_buffer;
137
138public:
139 void loadFromString(const std::string& xmlContent) override {
140 m_buffer.assign(xmlContent.begin(), xmlContent.end());
141 m_buffer.push_back('\0'); // Null-terminate the buffer.
142
143 try {
144 m_document.parse<0>(m_buffer.data());
145 } catch (const ::rapidxml::parse_error& e) {
146 throw musx::xml::load_error(e.what());
147 }
148 }
150 void loadFromString(const std::vector<char>& xmlContent) override {
151 m_buffer = xmlContent;
152 m_buffer.push_back('\0'); // Null-terminate the buffer.
153
154 try {
155 m_document.parse<0>(m_buffer.data());
156 } catch (const ::rapidxml::parse_error& e) {
157 throw musx::xml::load_error(e.what());
158 }
159 }
161 std::shared_ptr<IXmlElement> getRootElement() const override {
162 ::rapidxml::xml_node<>* root = m_document.first_node();
163 return root ? std::make_shared<Element>(root) : nullptr;
164 }
165};
166
167} // namespace rapidxml
168} // namespace xml
169} // namespace musx
170
171#endif // MUSX_USE_RAPIDXML
Interface for an XML attribute.
Definition XmlInterface.h:65
Interface for an XML document.
Definition XmlInterface.h:230
Interface for an XML element.
Definition XmlInterface.h:133
Exception for load xml error.
Definition XmlInterface.h:46
Implementation of IXmlAttribute using rapidxml.
Definition RapidXmlImpl.h:51
std::string getName() const override
Gets the name of the attribute.
Definition RapidXmlImpl.h:59
std::string getValue() const override
Gets the value of the attribute.
Definition RapidXmlImpl.h:60
std::shared_ptr< IXmlAttribute > nextAttribute() const override
Advances to the next attribute.
Definition RapidXmlImpl.h:62
Implementation of IXmlDocument using rapidxml.
Definition RapidXmlImpl.h:134
void loadFromString(const std::string &xmlContent) override
Loads XML content from a string.
Definition RapidXmlImpl.h:138
std::shared_ptr< IXmlElement > getRootElement() const override
Gets the root element of the document.
Definition RapidXmlImpl.h:160
Implementation of IXmlElement using rapidxml.
Definition RapidXmlImpl.h:73
std::shared_ptr< IXmlAttribute > findAttribute(const std::string &tagName) const override
Finds the first attribute.
Definition RapidXmlImpl.h:96
std::string getTagName() const override
Gets the tag name of the element.
Definition RapidXmlImpl.h:85
std::string getText() const override
Gets the text content of the element.
Definition RapidXmlImpl.h:87
std::shared_ptr< IXmlElement > getPreviousSibling(const std::string &tagName={}) const override
Gets the previous sibling element.
Definition RapidXmlImpl.h:111
std::shared_ptr< IXmlAttribute > getFirstAttribute() const override
Gets the first attribute.
Definition RapidXmlImpl.h:91
std::shared_ptr< IXmlElement > getFirstChildElement(const std::string &tagName={}) const override
Finds the first child element.
Definition RapidXmlImpl.h:101
std::shared_ptr< IXmlElement > getNextSibling(const std::string &tagName={}) const override
Gets the next sibling element.
Definition RapidXmlImpl.h:106
std::shared_ptr< IXmlElement > getParent() const override
Gets the parent element.
Definition RapidXmlImpl.h:123
object model for musx file (enigmaxml)
Definition BaseClasses.h:32