5#include "Stroika/Foundation/Streams/MemoryStream.h"
7namespace Stroika::Foundation::DataExchange::XML::DOM {
14 template <Characters::IConvertibleToString ST>
15 inline XPath::Expression::Expression (ST&& e,
const Options& o)
16 : Expression{String{e}, o}
19 inline String XPath::Expression::GetExpression ()
const
21 return fRep_->GetExpression ();
23 inline auto XPath::Expression::GetOptions () const -> Options
25 return fRep_->GetOptions ();
27 inline auto XPath::Expression::GetRep () const -> shared_ptr<const IRep>
37 inline Node::Ptr::Ptr (
const shared_ptr<IRep>& from)
41 inline Node::Ptr::Ptr (nullptr_t)
47 if (fRep_ ==
nullptr) [[unlikely]] {
48 return rhs.fRep_ ==
nullptr;
50 if (rhs.fRep_ ==
nullptr) {
53 return fRep_->Equals (rhs.fRep_.get ());
57 return fRep_ ==
nullptr;
59 inline Node::Ptr::operator bool ()
const
61 return fRep_.operator bool ();
63 inline Node::Type Node::Ptr::GetNodeType ()
const
66 return fRep_->GetNodeType ();
70 Require (GetNodeType () == eAttributeNT or GetNodeType () == eElementNT);
71 return GetRep ()->GetName ();
75 Require (GetNodeType () == eAttributeNT or GetNodeType () == eElementNT);
76 GetRep ()->SetName (name);
80 Require (GetNodeType () == eAttributeNT or GetNodeType () == eElementNT);
81 return GetRep ()->GetValue ();
85 Require (GetNodeType () == eAttributeNT or GetNodeType () == eElementNT);
86 return GetRep ()->SetValue (v);
97 return fRep_->GetParentNode ();
119 : Node::Ptr{p != nullptr and p.GetNodeType () == Node::eElementNT ? p : nullptr}
121 Require (
PeekRep () ==
nullptr or GetNodeType () == eElementNT);
126 Require (
PeekRep () ==
nullptr or GetNodeType () == eElementNT);
129 : Node::Ptr{get<Node::Ptr> (r)}
131 Require (
PeekRep () ==
nullptr or GetNodeType () == eElementNT);
135 return GetRep ()->GetAttribute (attrName);
139 return GetRep ()->GetAttribute (attrName) != nullopt;
143 if (
auto o = GetRep ()->GetAttribute (attrName)) {
150 GetRep ()->SetAttribute (attrName, v);
152 template <same_as<VariantValue> VV>
155 GetRep ()->SetAttribute (attrName, v ==
nullptr ? optional<String>{} : v.template As<String> ());
159 static const NameWithNamespace kID_{
"id"sv};
160 return GetRep ()->GetAttribute (kID_);
164 if (
auto v = GetAttribute (kXMLNS)) {
171 SetAttribute (kXMLNS, defaultNS == nullopt ? optional<String>{} : defaultNS->As<
String> ());
175 Require (e.
GetOptions ().fResultTypeIndex == XPath::ResultTypeIndex_v<Node::Ptr>);
176 if (optional<XPath::Result> o = GetRep ()->LookupOne (e)) {
186 Require (e.
GetOptions ().fResultTypeIndex == XPath::ResultTypeIndex_v<Node::Ptr>);
187 return GetRep ()->Lookup (e).Map<
Iterable<String>> ([] (
const XPath::Result& e) -> optional<String> {
189 switch (ep.GetNodeType ()) {
190 case Node::Type::eAttributeNT:
191 case Node::Type::eElementNT:
200 Require (e.
GetOptions ().fResultTypeIndex == XPath::ResultTypeIndex_v<Node::Ptr>);
201 if (optional<XPath::Result> o = GetRep ()->LookupOne (e)) {
211 template <same_as<VariantValue> VV>
212 inline void Element::Ptr::SetValue (
const VV& v)
214 SetValue (v.template As<String> ());
216 template <same_as<VariantValue> VV>
217 inline void Element::Ptr::SetValue (
const XPath::Expression& e,
const VV& v)
219 SetValue (e, v.template As<String> ());
223 return GetRep ()->InsertElement (eltName, afterNode);
227 return GetRep ()->AppendElement (eltName);
231 return GetRep ()->AppendImportedNode (cloneFrom);
235 return GetRep ()->InsertImportedNode (cloneFrom, afterNode);
239 auto r = Append (eltName);
243 template <same_as<VariantValue> VV>
246 auto r = Append (eltName);
247 r.SetValue (v.template As<String> ());
253 auto r = Append (eltName);
259 template <same_as<VariantValue> VV>
263 return Append (eltName, v.template As<String> ());
282 if (parent ==
nullptr) {
285 newNode = parent.Append (newEltName);
288 newNode = parent.Insert (newEltName, *
this);
291 Ensure (newNode.GetParent () == parent);
302 return GetRep ()->GetChildren ();
309 return eltNode ==
nullptr ? optional<Ptr>{} : eltNode;
314 return Element::Ptr{GetRep ()->GetChildElementByID (
id)};
322 Require (e.
GetOptions ().fResultTypeIndex == XPath::ResultTypeIndex_v<Node::Ptr>);
323 if (optional<XPath::Result> o = GetRep ()->LookupOne (e)) {
324 return get<Node::Ptr> (*o);
330 return GetRep ()->Lookup (e);
336 return ep !=
nullptr ? ep : optional<Element::Ptr>{};
355 inline Document::Ptr::Ptr (nullptr_t)
359 inline Document::Ptr::Ptr (
const shared_ptr<IRep>& rep)
368 inline bool Document::Ptr::operator== (nullptr_t)
const
370 return fRep_ ==
nullptr;
372 inline bool Document::Ptr::GetStandalone ()
const
374 return GetRep ()->GetStandalone ();
376 inline void Document::Ptr::SetStandalone (
bool standalone)
378 GetRep ()->SetStandalone (standalone);
382 GetRep ()->Write (to, options);
388 GetRep ()->Write (bufferedOutput, options);
393 return GetRep ()->GetChildren ();
398 for (
Node::Ptr ni : GetRep ()->GetChildren ()) {
399 if (ni.GetNodeType () == Node::eElementNT) {
408 return GetRep ()->ReplaceRootElement (newEltName, namespacePrefix);
413 return GetRootElement ().LookupOneElement (e);
418 return GetRootElement ().Lookup (e);
423 return GetRootElement ().LookupElements (e);
#define RequireNotNull(p)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual void Write(const Streams::OutputStream::Ptr< byte > &to, const SerializationOptions &options={}) const
The document as XML: to a byte stream as UTF-8, with no byte order mark - or as a String.
nonvirtual Iterable< Node::Ptr > GetChildren() const
nonvirtual Traversal::Iterable< Element::Ptr > LookupElements(const XPath::Expression &e) const
shorthand for GetRootElement ().LookupElements (e) - so requires root element exists
nonvirtual shared_ptr< IRep > GetRep() const
nonvirtual Element::Ptr GetRootElement() const
always returns Node of eElement or return nullptr if none
nonvirtual Element::Ptr LookupOneElement(const XPath::Expression &e) const
shorthand for GetRootElement ().LookupOneElement (e) - so requires root element exists
nonvirtual Traversal::Iterable< XPath::Result > Lookup(const XPath::Expression &e) const
shorthand for GetRootElement ().Lookup (e) - so requires root element exists
nonvirtual Element::Ptr ReplaceRootElement(const NameWithNamespace &newEltName, const optional< String > &namespacePrefix=nullopt) const
Make this the document's root element - and say HOW its namespace is declared on it,...
nonvirtual Ptr GetParent() const
nonvirtual Node::Ptr LookupOneNode(const XPath::Expression &e) const
nonvirtual shared_ptr< IRep > PeekRep() const
return the associated shared_ptr (can be nullptr)
nonvirtual optional< String > GetID() const
nonvirtual optional< URI > GetDefaultNamespace() const
nonvirtual Traversal::Iterable< Element::Ptr > LookupElements(const XPath::Expression &e) const
nonvirtual Ptr GetChildByID(const String &id) const
nonvirtual Ptr Append(const NameWithNamespace &eltName)
nonvirtual Element::Ptr LookupOneElement(const XPath::Expression &e) const
nonvirtual Ptr Replace(const NameWithNamespace &newEltName)
nonvirtual Traversal::Iterable< XPath::Result > Lookup(const XPath::Expression &e) const
nonvirtual Ptr AppendIf(const NameWithNamespace &eltName, const optional< String > &v)
Trivial wrapper on AppendElement, but if v is missing then this is a no-op.
nonvirtual void SetDefaultNamespace(const optional< URI > defaultNS=nullopt)
Sets the xmlns attribute of this element.
nonvirtual void SetAttribute(const NameWithNamespace &attrName, const optional< String > &v)
nonvirtual optional< String > GetAttribute(const NameWithNamespace &attrName) const
nonvirtual Iterable< Ptr > GetChildElements() const
nonvirtual Ptr Insert(const NameWithNamespace &eltName, const Node::Ptr &afterNode)
Insert Element (after argument node) inside of this 'Element'.
nonvirtual shared_ptr< IRep > GetRep() const
return the associated shared_ptr (cannot be nullptr)
nonvirtual Traversal::Iterable< String > GetValues(const XPath::Expression &e) const
nonvirtual Iterable< Node::Ptr > GetChildNodes() const
nonvirtual Ptr ImportNode(const Node::Ptr &cloneFrom)
Append a deep CLONE of 'cloneFrom' - an element of any document - to this element's children.
nonvirtual bool HasAttribute(const NameWithNamespace &attrName) const
Node::Ptr is a smart pointer to a Node::IRep.
nonvirtual Ptr GetParentNode() const
nonvirtual void SetValue(const String &v)
nonvirtual NameWithNamespace GetName() const
nonvirtual void SetName(const NameWithNamespace &name)
nonvirtual bool operator==(const Ptr &rhs) const
nonvirtual shared_ptr< IRep > PeekRep() const
return the associated shared_ptr (can be nullptr)
nonvirtual String GetValue() const
nonvirtual shared_ptr< IRep > GetRep() const
return the associated shared_ptr (cannot be nullptr)
nonvirtual Options GetOptions() const
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
OutputStream<>::Ptr is Smart pointer to a stream-based sink of data.
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
functional API which iterates over all members of an Iterable, applies a map function to each element...
void Throw(T &&e2Throw)
like the builtin C++ 'throw', but stamps in the current Activity context and does helpful,...
Ptr New(const InputStream::Ptr< byte > &src, optional< SeekableFlag > seekable={}, ReadAhead readAhead=eReadAheadAllowed)
Create an InputStream::Ptr<Character> from the arguments (usually binary source) - which can be used ...
An element's or attribute's name (local-name, not including a prefix), plus the namespace that name i...