9 #include <libxml/uri.h>
13 using std::unique_ptr;
39 children.push_back(std::move(child));
40 return children.back();
45 assert(std::count_if(children.begin(), children.end(),
46 [&](Children::value_type& v) {
return &v == &child; }) == 1);
47 auto it = std::find_if(children.begin(), children.end(),
48 [&](Children::value_type& v) {
return &v == &child; });
49 assert(it != children.end());
53 XMLElement::Attributes::iterator XMLElement::findAttribute(
string_ref name)
55 return find_if(attributes.begin(), attributes.end(),
56 [&](Attribute& a) {
return a.first == name; });
58 XMLElement::Attributes::const_iterator XMLElement::findAttribute(
string_ref name)
const
60 return find_if(attributes.begin(), attributes.end(),
61 [&](
const Attribute& a) {
return a.first == name; });
66 assert(findAttribute(name) == attributes.end());
67 attributes.push_back(make_pair(name.
str(), value.
str()));
72 auto it = findAttribute(name);
73 if (it != attributes.end()) {
74 it->second = value.
str();
76 attributes.push_back(make_pair(name.
str(), value.
str()));
82 auto it = findAttribute(name);
83 if (it != attributes.end()) {
115 assert(children.empty());
121 std::vector<const XMLElement*> result;
122 for (
auto& c : children) {
123 if (c.getName() == name) {
124 result.push_back(&c);
132 for (
auto& c : children) {
133 if (c.getName() == name) {
145 size_t& fromIndex)
const
147 for (
auto i :
xrange(fromIndex, children.size())) {
148 if (children[i].
getName() == name) {
153 for (
auto i :
xrange(fromIndex)) {
154 if (children[i].
getName() == name) {
165 for (
auto& c : children) {
166 if ((c.getName() == name) &&
167 (c.getAttribute(attName) == attValue)) {
178 name, attName, attValue);
187 "Missing tag \"" << name <<
"\".");
211 result.addAttribute(attName, attValue);
224 return child ? child->getData() : defaultValue;
242 child->setData(value);
255 return findAttribute(name) != attributes.end();
260 auto it = findAttribute(attName);
261 if (it == attributes.end()) {
271 auto it = findAttribute(attName);
272 return (it == attributes.end()) ? defaultValue : it->second;
276 bool defaultValue)
const
278 auto it = findAttribute(attName);
279 return (it == attributes.end()) ? defaultValue
284 int defaultValue)
const
286 auto it = findAttribute(attName);
287 return (it == attributes.end()) ? defaultValue
292 unsigned& result)
const
294 auto it = findAttribute(attName);
295 if (it != attributes.end()) {
312 string indent(indentNum,
' ');
313 result << indent <<
'<' <<
getName();
314 for (
auto& p : attributes) {
315 result <<
' ' << p.first
318 if (children.empty()) {
322 result << '>
' << XMLEscape(data) << "</"
323 << getName() << ">\n";
327 for (auto& c : children) {
328 c.dump(result, indentNum + 2);
330 result << indent << "</" << getName() << ">\n";
334 string XMLElement::XMLEscape(const string& str)
336 xmlChar* buffer = xmlEncodeEntitiesReentrant(
337 nullptr, reinterpret_cast<const xmlChar*>(str.c_str()));
338 string result = reinterpret_cast<const char*>(buffer);
343 static unique_ptr<FileContext> lastSerializedFileContext;
344 unique_ptr<FileContext> XMLElement::getLastSerializedFileContext()
346 return std::move(lastSerializedFileContext); // this also sets value to nullptr;
348 // version 1: initial version
349 // version 2: removed 'context
' tag
350 // also removed 'parent
', but that was never serialized
351 // 2b: (no need to increase version) name and data members are
352 // serialized as normal members instead of constructor parameters
353 // 2c: (no need to increase version) attributes were initially stored as
354 // map<string, string>, later this was changed to
355 // vector<pair<string, string>>. To keep bw-compat the serialize()
356 // method converted between these two formats. Though (by luck) in
357 // the XML output both datastructures are serialized to the same
358 // format, so we can drop this conversion step without breaking
360 template<typename Archive>
361 void XMLElement::serialize(Archive& ar, unsigned version)
363 ar.serialize("name", name);
364 ar.serialize("data", data);
365 ar.serialize("attributes", attributes);
366 ar.serialize("children", children);
368 if (ar.versionBelow(version, 2)) {
369 assert(ar.isLoader());
370 unique_ptr<FileContext> context;
371 ar.serialize("context", context);
373 assert(!lastSerializedFileContext.get());
374 lastSerializedFileContext = std::move(context);
378 INSTANTIATE_SERIALIZE_METHODS(XMLElement);
380 } // namespace openmsx