1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngxml/xpath/XPathObject.hpp>
  7 #include <sngxml/dom/Element.hpp>
  8 #include <soulng/util/Unicode.hpp>
  9 
 10 namespace sngxml { namespace xpath {
 11 
 12 using namespace soulng::unicode;
 13 
 14 XPathObject::XPathObject(XPathObjectType type_) : type(type_)
 15 {
 16 }
 17 
 18 XPathObject::~XPathObject()
 19 {
 20 }
 21 
 22 XPathNodeSet::XPathNodeSet() : XPathObject(XPathObjectType::nodeSet)
 23 {
 24 }
 25 
 26 void XPathNodeSet::Add(sngxml::dom::Node* node)
 27 {
 28     nodes.InternalAddNode(node);
 29 }
 30 
 31 std::std::unique_ptr<dom::Node>XPathNodeSet::ToDom() const
 32 {
 33     std::unique_ptr<dom::Element> result(new dom::Element(U"nodeset"));
 34     result->SetAttribute(U"length"ToUtf32(std::to_string(nodes.Length())));
 35     int n = nodes.Length();
 36     for (int i = 0; i < n; ++i)
 37     {
 38         dom::Node* node = nodes[i];
 39         if (node->GetNodeType() == dom::NodeType::attributeNode)
 40         {
 41             std::unique_ptr<dom::Element> element(new dom::Element(U"attribute"));
 42             std::unique_ptr<dom::Node> clonedAttrNode = node->CloneNode(false);
 43             std::unique_ptr<dom::Attr> clonedAttr(static_cast<dom::Attr*>(clonedAttrNode.get()));
 44             element->AddAttribute(std::move(clonedAttr));
 45             result->AppendChild(std::unique_ptr<dom::Node>(element.release()));
 46         }
 47         else
 48         {
 49             std::u32string nodeName;
 50             switch (node->GetNodeType())
 51             {
 52             case dom::NodeType::documentNode:
 53             {
 54                 nodeName = U"document";
 55                 break;
 56             }
 57             case dom::NodeType::elementNode:
 58             {
 59                 nodeName = U"element";
 60                 break;
 61             }
 62             case dom::NodeType::textNode:
 63             {
 64                 nodeName = U"text";
 65                 break;
 66             }
 67             case dom::NodeType::cdataSectionNode:
 68             {
 69                 nodeName = U"cdataSection";
 70                 break;
 71             }
 72             case dom::NodeType::commentNode:
 73             {
 74                 nodeName = U"comment";
 75                 break;
 76             }
 77             case dom::NodeType::processingInstructionNode:
 78             {
 79                 nodeName = U"processingInstruction";
 80                 break;
 81             }
 82             }
 83             std::unique_ptr<dom::Element> element(new dom::Element(nodeName));
 84             element->AppendChild(node->CloneNode(true));
 85             result->AppendChild(std::unique_ptr<dom::Node>(element.release()));
 86         }
 87     }
 88     return std::unique_ptr<dom::Node>(result.release());
 89 }
 90 
 91 XPathBoolean::XPathBoolean(bool value_) : XPathObject(XPathObjectType::boolean)value(value_)
 92 {
 93 }
 94 
 95 std::std::unique_ptr<dom::Node>XPathBoolean::ToDom() const
 96 {
 97     std::unique_ptr<dom::Element> result(new dom::Element(U"boolean"));
 98     std::u32string val = U"true";
 99     if (!value)
100     {
101         val = U"false";
102     }
103     result->SetAttribute(U"value"val);
104     return std::unique_ptr<dom::Node>(result.release());
105 }
106 
107 XPathNumber::XPathNumber(double value_) : XPathObject(XPathObjectType::number)value(value_)
108 {
109 }
110 
111 std::std::unique_ptr<dom::Node>XPathNumber::ToDom() const
112 {
113     std::unique_ptr<dom::Element> result(new dom::Element(U"number"));
114     result->SetAttribute(U"value"ToUtf32(std::to_string(value)));
115     return std::unique_ptr<dom::Node>(result.release());
116 }
117 
118 XPathString::XPathString(const std::u32string& value_) : XPathObject(XPathObjectType::string)value(value_)
119 {
120 }
121 
122 std::std::unique_ptr<dom::Node>XPathString::ToDom() const
123 {
124     std::unique_ptr<dom::Element> result(new dom::Element(U"string"));
125     result->SetAttribute(U"value"value);
126     return std::unique_ptr<dom::Node>(result.release());
127 }
128 
129 } } // namespace sngxml::xpath