12#include <promeki/config.h>
13#if PROMEKI_ENABLE_CORE
26PROMEKI_NAMESPACE_BEGIN
66 explicit XmlName(
const String &local) : _local(local) {}
69 XmlName(
const String &uri,
const String &local) : _uri(uri), _local(local) {}
72 XmlName(
const String &uri,
const String &prefix,
const String &local)
73 : _uri(uri), _prefix(prefix), _local(local) {}
81 static XmlName parseClark(
const String &clark);
84 bool isValid()
const {
return !_local.isEmpty(); }
87 const String &uri()
const {
return _uri; }
90 const String &prefix()
const {
return _prefix; }
93 const String &local()
const {
return _local; }
96 bool hasNamespace()
const {
return !_uri.isEmpty(); }
99 String qualified()
const;
102 String clark()
const;
105 String toString()
const {
return clark(); }
108 bool operator==(
const XmlName &other)
const {
109 return _uri == other._uri && _local == other._local;
113 bool operator!=(
const XmlName &other)
const {
return !(*
this == other); }
150 XmlParseError() =
default;
153 bool ok()
const {
return _status == pugi::status_ok; }
156 bool isError()
const {
return !ok(); }
159 explicit operator bool()
const {
return ok(); }
162 pugi::xml_parse_status pugiStatus()
const {
return _status; }
165 const String &message()
const {
return _message; }
168 size_t offset()
const {
return _offset; }
171 int line()
const {
return _line; }
174 int column()
const {
return _column; }
185 Error toError()
const;
188 String toString()
const;
191 bool operator==(
const XmlParseError &other)
const {
192 return _status == other._status && _offset == other._offset &&
193 _message == other._message;
197 bool operator!=(
const XmlParseError &other)
const {
return !(*
this == other); }
200 friend class XmlDocument;
201 friend class XmlElement;
210 void setFromPugi(
const pugi::xml_parse_result &result,
const String &source);
212 pugi::xml_parse_status _status = pugi::status_ok;
245 PROMEKI_SHARED_FINAL(XmlData)
246 pugi::xml_document doc;
249 XmlData(
const XmlData &other);
250 XmlData &operator=(
const XmlData &other);
251 XmlData(XmlData &&) =
delete;
252 XmlData &operator=(XmlData &&) =
delete;
269 XmlAttribute() =
default;
272 XmlAttribute(String rawName, String value)
273 : _name(std::move(rawName)), _value(std::move(value)) {}
276 XmlAttribute(XmlName qname, String value);
279 XmlAttribute(String rawName, XmlName qname, String value)
280 : _name(std::move(rawName)), _qname(std::move(qname)), _value(std::move(value)) {}
283 const String &name()
const {
return _name; }
286 const XmlName &qname()
const {
return _qname; }
289 const String &value()
const {
return _value; }
292 void setName(
const String &name) { _name = name; }
295 void setQName(
const XmlName &qname) { _qname = qname; }
298 void setValue(
const String &value) { _value = value; }
301 bool isValid()
const {
return !_name.isEmpty(); }
304 bool operator==(
const XmlAttribute &other)
const {
305 return _name == other._name && _value == other._value;
309 bool operator!=(
const XmlAttribute &other)
const {
return !(*
this == other); }
363 static XmlElement parse(
const String &str, XmlParseError *err =
nullptr);
366 XmlElement() =
default;
369 explicit XmlElement(
const String &name);
372 bool isValid()
const;
384 XmlName qname()
const;
387 void setName(
const String &name);
397 Map<String, String> namespaces()
const;
402 bool hasAttribute(
const String &name)
const;
405 bool hasAttribute(
const XmlName &qname)
const;
413 String attribute(
const String &name, Error *err =
nullptr)
const;
424 String attribute(
const XmlName &qname, Error *err =
nullptr)
const;
427 void setAttribute(
const String &name,
const String &value);
440 void setAttribute(
const XmlName &qname,
const String &value);
446 bool removeAttribute(
const String &name);
452 bool removeAttribute(
const XmlName &qname);
455 List<XmlAttribute> attributes()
const;
460 bool hasChild(
const String &name)
const;
463 bool hasChild(
const XmlName &qname)
const;
468 XmlElement child(
const String &name)
const;
476 XmlElement child(
const XmlName &qname)
const;
479 List<XmlElement> elements()
const;
482 List<XmlElement> elementsNamed(
const String &name)
const;
485 List<XmlElement> elementsNamed(
const XmlName &qname)
const;
500 XmlElement selectFirst(
const String &query, Error *err =
nullptr)
const;
508 List<XmlElement> selectAll(
const String &query, Error *err =
nullptr)
const;
518 XmlAttribute selectFirstAttribute(
const String &query, Error *err =
nullptr)
const;
521 List<XmlAttribute> selectAllAttributes(
const String &query, Error *err =
nullptr)
const;
537 XmlElement elementByPath(
const String &path)
const;
540 List<XmlNode> children()
const;
558 void setText(
const String &text);
572 void appendElement(
const String &name);
575 void appendElement(
const String &name,
const String &text);
586 void appendElement(
const XmlName &qname);
589 void appendElement(
const XmlName &qname,
const String &text);
592 void appendText(
const String &text);
595 void appendCData(
const String &text);
598 void appendComment(
const String &text);
601 void appendProcessingInstruction(
const String &target,
const String &data);
604 void appendChild(
const XmlElement &child);
607 void appendChild(
const XmlNode &node);
618 void appendChild(
const XmlDocument &doc);
631 XmlDocument toDocument()
const;
636 void prependElement(
const String &name);
639 void prependElement(
const String &name,
const String &text);
642 void prependChild(
const XmlElement &child);
645 void prependChild(
const XmlNode &node);
648 void prependChild(
const XmlDocument &doc);
659 void insertChildAt(
size_t index,
const XmlElement &child);
662 void insertChildAt(
size_t index,
const XmlNode &node);
670 bool removeChild(
const String &name);
676 bool removeChild(
const XmlName &qname);
682 bool removeChildAt(
size_t index);
688 size_t removeAllNamed(
const String &name);
694 size_t removeAllNamed(
const XmlName &qname);
697 size_t childCount()
const;
702 void prependAttribute(
const String &name,
const String &value);
705 void prependAttribute(
const XmlName &qname,
const String &value);
712 void insertAttributeAt(
size_t index,
const String &name,
const String &value);
715 void insertAttributeAt(
size_t index,
const XmlName &qname,
const String &value);
718 size_t attributeCount()
const;
727 String toString(
unsigned int indent = 0)
const;
730 void forEachElement(Function<
void(
const XmlElement &)> func)
const;
733 bool operator==(
const XmlElement &other)
const;
736 bool operator!=(
const XmlElement &other)
const {
return !(*
this == other); }
739 friend class XmlDocument;
740 friend class XmlNode;
742 SharedPtr<XmlData> _d = SharedPtr<XmlData>::create();
744 explicit XmlElement(
const SharedPtr<XmlData> &d) : _d(d) {}
747 pugi::xml_node rootNode()
const;
750 void resetTo(
const pugi::xml_node &node);
783 PROMEKI_DATATYPE(XmlDocument, DataTypeXmlDocument, 1)
794 Error writeToStream(DataStream &s) const;
800 template <uint32_t V> static Result<XmlDocument> readFromStream(DataStream &s);
813 static XmlDocument parse(const String &str, XmlParseError *err =
nullptr);
826 static Result<XmlDocument> fromString(const String &str);
837 static XmlDocument loadFromPath(const String &path, XmlParseError *err =
nullptr);
851 Error saveToPath(const String &path,
unsigned int indent = 0) const;
854 XmlDocument() = default;
862 explicit XmlDocument(const XmlElement &root);
865 bool isValid() const;
870 String declarationVersion() const;
873 String declarationEncoding() const;
876 String declarationStandalone() const;
884 void setDeclaration(const String &version = "1.0",
885 const String &encoding = "UTF-8",
886 const String &standalone = String());
891 String doctype() const;
894 void setDoctype(const String &doctype);
903 XmlElement root() const;
906 XmlElement selectFirst(const String &query, Error *err =
nullptr)
const {
907 return root().selectFirst(query, err);
911 List<XmlElement> selectAll(
const String &query, Error *err =
nullptr)
const {
912 return root().selectAll(query, err);
916 XmlElement elementByPath(
const String &path)
const {
return root().elementByPath(path); }
924 void setRoot(
const XmlElement &elem);
927 void appendComment(
const String &text);
930 void appendProcessingInstruction(
const String &target,
const String &data);
939 String toString(
unsigned int indent = 0)
const;
942 bool operator==(
const XmlDocument &other)
const;
945 bool operator!=(
const XmlDocument &other)
const {
return !(*
this == other); }
948 friend class XmlElement;
949 friend class XmlNode;
951 SharedPtr<XmlData> _d = SharedPtr<XmlData>::create();
953 explicit XmlDocument(
const SharedPtr<XmlData> &d) : _d(d) {}
981 ProcessingInstruction,
989 static XmlNode undefined();
992 XmlNode(
const XmlElement &elem);
995 static XmlNode makeText(
const String &body);
998 static XmlNode makeCData(
const String &body);
1001 static XmlNode makeComment(
const String &body);
1004 static XmlNode makeProcessingInstruction(
const String &target,
const String &data);
1007 Type type()
const {
return _type; }
1010 bool isNull()
const {
return _type == Null; }
1012 bool isUndefined()
const {
return _type == Undefined; }
1014 bool isElement()
const {
return _type == Element; }
1016 bool isText()
const {
return _type == Text; }
1018 bool isCData()
const {
return _type == CData; }
1020 bool isComment()
const {
return _type == Comment; }
1022 bool isProcessingInstruction()
const {
return _type == ProcessingInstruction; }
1025 XmlElement toElement()
const;
1035 String text()
const;
1038 String piTarget()
const;
1041 String toString()
const;
1044 bool operator==(
const XmlNode &other)
const;
1047 bool operator!=(
const XmlNode &other)
const {
return !(*
this == other); }
1051 XmlElement _element;
1063inline DataStream &operator<<(DataStream &stream,
const XmlElement &elem) {
1064 stream.beginFrame(DataTypeXmlElement, 1);
1065 stream << elem.toString(0);
1073inline DataStream &operator>>(DataStream &stream, XmlElement &elem) {
1074 if (!stream.readFrame(DataTypeXmlElement)) {
1075 elem = XmlElement();
1080 if (stream.status() != DataStream::Ok) {
1081 elem = XmlElement();
1087 if (text.isEmpty()) {
1088 elem = XmlElement();
1092 elem = XmlElement::parse(text, &perr);
1094 stream.setError(DataStream::ReadCorruptData,
1095 String(
"XmlElement::parse failed: ") + perr.toString());
1100PROMEKI_NAMESPACE_END
1102PROMEKI_FORMAT_VIA_TOSTRING(promeki::XmlDocument);
1103PROMEKI_FORMAT_VIA_TOSTRING(promeki::XmlElement);