1/*
2 * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15
16#include <aws/core/utils/xml/XmlSerializer.h>
17
18#include <aws/core/utils/StringUtils.h>
19#include <aws/core/external/tinyxml2/tinyxml2.h>
20
21#include <utility>
22#include <algorithm>
23#include <iostream>
24
25using namespace Aws::Utils::Xml;
26using namespace Aws::Utils;
27
28Aws::String Aws::Utils::Xml::DecodeEscapedXmlText(const Aws::String& textToDecode)
29{
30 Aws::String decodedString = textToDecode;
31 StringUtils::Replace(decodedString, "&quot;", "\"");
32 StringUtils::Replace(decodedString, "&apos;", "'");
33 StringUtils::Replace(decodedString, "&lt;", "<");
34 StringUtils::Replace(decodedString, "&gt;", ">");
35 StringUtils::Replace(decodedString, "&amp;", "&");
36
37 return decodedString;
38}
39
40XmlNode::XmlNode(const XmlNode& other) : m_node(other.m_node), m_doc(other.m_doc)
41{
42}
43
44XmlNode& XmlNode::operator=(const XmlNode& other)
45{
46 if(this == &other)
47 {
48 return *this;
49 }
50
51 m_node = other.m_node;
52 m_doc = other.m_doc;
53
54 return *this;
55}
56
57const Aws::String XmlNode::GetName() const
58{
59 return m_node->Value();
60}
61
62void XmlNode::SetName(const Aws::String& name)
63{
64 m_node->SetValue(name.c_str(), false);
65}
66
67const Aws::String XmlNode::GetAttributeValue(const Aws::String& name) const
68{
69 auto pointer = m_node->ToElement()->Attribute(name.c_str(), nullptr);
70 return pointer ? pointer : "";
71}
72
73void XmlNode::SetAttributeValue(const Aws::String& name, const Aws::String& value)
74{
75 m_node->ToElement()->SetAttribute(name.c_str(), value.c_str());
76}
77
78bool XmlNode::HasNextNode() const
79{
80 return m_node->NextSibling() != nullptr;
81}
82
83XmlNode XmlNode::NextNode() const
84{
85 return XmlNode(m_node->NextSiblingElement(), *m_doc);
86}
87
88XmlNode XmlNode::NextNode(const char* name) const
89{
90 return XmlNode(m_node->NextSiblingElement(name), *m_doc);
91}
92
93XmlNode XmlNode::NextNode(const Aws::String& name) const
94{
95 return NextNode(name.c_str());
96}
97
98XmlNode XmlNode::FirstChild() const
99{
100 return XmlNode(m_node->FirstChildElement(), *m_doc);
101}
102
103XmlNode XmlNode::FirstChild(const char* name) const
104{
105 return XmlNode(m_node->FirstChildElement(name), *m_doc);
106}
107
108XmlNode XmlNode::FirstChild(const Aws::String& name) const
109{
110 return FirstChild(name.c_str());
111}
112
113bool XmlNode::HasChildren() const
114{
115 return !m_node->NoChildren();
116}
117
118XmlNode XmlNode::Parent() const
119{
120 return XmlNode(m_node->Parent()->ToElement(), *m_doc);
121}
122
123Aws::String XmlNode::GetText() const
124{
125 if (m_node != nullptr)
126 {
127 Aws::External::tinyxml2::XMLPrinter printer;
128 Aws::External::tinyxml2::XMLNode* node = m_node->FirstChild();
129 while (node != nullptr)
130 {
131 node->Accept(&printer);
132 node = node->NextSibling();
133 }
134
135 return printer.CStr();
136 }
137
138 return {};
139}
140
141void XmlNode::SetText(const Aws::String& textValue)
142{
143 if (m_node != nullptr)
144 {
145 Aws::External::tinyxml2::XMLText* text = m_doc->m_doc->NewText(textValue.c_str());
146 m_node->InsertEndChild(text);
147 }
148}
149
150XmlNode XmlNode::CreateChildElement(const Aws::String& name)
151{
152 Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str());
153 return XmlNode(m_node->InsertEndChild(element), *m_doc);
154}
155
156XmlNode XmlNode::CreateSiblingElement(const Aws::String& name)
157{
158 Aws::External::tinyxml2::XMLElement* element = m_doc->m_doc->NewElement(name.c_str());
159 return XmlNode(m_node->Parent()->InsertEndChild(element), *m_doc);
160}
161
162bool XmlNode::IsNull()
163{
164 return m_node == nullptr;
165}
166
167static const char* XML_SERIALIZER_ALLOCATION_TAG = "XmlDocument";
168
169XmlDocument::XmlDocument()
170{
171 m_doc = Aws::New<Aws::External::tinyxml2::XMLDocument>(XML_SERIALIZER_ALLOCATION_TAG, true, Aws::External::tinyxml2::Whitespace::PRESERVE_WHITESPACE);
172}
173
174XmlDocument::XmlDocument(XmlDocument&& doc) : m_doc{ doc.m_doc } // take the innards
175{
176 doc.m_doc = nullptr; // leave nothing behind
177}
178
179XmlDocument::~XmlDocument()
180{
181 Aws::Delete(m_doc);
182}
183
184XmlNode XmlDocument::GetRootElement() const
185{
186 return XmlNode(m_doc->FirstChildElement(), *this);
187}
188
189bool XmlDocument::WasParseSuccessful() const
190{
191 return !m_doc->Error();
192}
193
194Aws::String XmlDocument::GetErrorMessage() const
195{
196 return !WasParseSuccessful() ? m_doc->ErrorName() : "";
197}
198
199Aws::String XmlDocument::ConvertToString() const
200{
201 Aws::External::tinyxml2::XMLPrinter printer;
202 printer.PushHeader(false, true);
203 m_doc->Accept(&printer);
204
205 return printer.CStr();
206}
207
208XmlDocument XmlDocument::CreateFromXmlStream(Aws::IOStream& xmlStream)
209{
210 Aws::String xmlString((Aws::IStreamBufIterator(xmlStream)), Aws::IStreamBufIterator());
211 return CreateFromXmlString(xmlString);
212}
213
214XmlDocument XmlDocument::CreateFromXmlString(const Aws::String& xmlText)
215{
216 XmlDocument xmlDocument;
217 xmlDocument.m_doc->Parse(xmlText.c_str(), xmlText.size());
218 return xmlDocument;
219}
220
221XmlDocument XmlDocument::CreateWithRootNode(const Aws::String& rootNodeName)
222{
223 XmlDocument xmlDocument;
224 Aws::External::tinyxml2::XMLElement* rootNode = xmlDocument.m_doc->NewElement(rootNodeName.c_str());
225 xmlDocument.m_doc->LinkEndChild(rootNode);
226
227 return xmlDocument;
228}
229
230