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 | |
25 | using namespace Aws::Utils::Xml; |
26 | using namespace Aws::Utils; |
27 | |
28 | Aws::String Aws::Utils::Xml::DecodeEscapedXmlText(const Aws::String& textToDecode) |
29 | { |
30 | Aws::String decodedString = textToDecode; |
31 | StringUtils::Replace(decodedString, """ , "\"" ); |
32 | StringUtils::Replace(decodedString, "'" , "'" ); |
33 | StringUtils::Replace(decodedString, "<" , "<" ); |
34 | StringUtils::Replace(decodedString, ">" , ">" ); |
35 | StringUtils::Replace(decodedString, "&" , "&" ); |
36 | |
37 | return decodedString; |
38 | } |
39 | |
40 | XmlNode::XmlNode(const XmlNode& other) : m_node(other.m_node), m_doc(other.m_doc) |
41 | { |
42 | } |
43 | |
44 | XmlNode& 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 | |
57 | const Aws::String XmlNode::GetName() const |
58 | { |
59 | return m_node->Value(); |
60 | } |
61 | |
62 | void XmlNode::SetName(const Aws::String& name) |
63 | { |
64 | m_node->SetValue(name.c_str(), false); |
65 | } |
66 | |
67 | const 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 | |
73 | void XmlNode::SetAttributeValue(const Aws::String& name, const Aws::String& value) |
74 | { |
75 | m_node->ToElement()->SetAttribute(name.c_str(), value.c_str()); |
76 | } |
77 | |
78 | bool XmlNode::HasNextNode() const |
79 | { |
80 | return m_node->NextSibling() != nullptr; |
81 | } |
82 | |
83 | XmlNode XmlNode::NextNode() const |
84 | { |
85 | return XmlNode(m_node->NextSiblingElement(), *m_doc); |
86 | } |
87 | |
88 | XmlNode XmlNode::NextNode(const char* name) const |
89 | { |
90 | return XmlNode(m_node->NextSiblingElement(name), *m_doc); |
91 | } |
92 | |
93 | XmlNode XmlNode::NextNode(const Aws::String& name) const |
94 | { |
95 | return NextNode(name.c_str()); |
96 | } |
97 | |
98 | XmlNode XmlNode::FirstChild() const |
99 | { |
100 | return XmlNode(m_node->FirstChildElement(), *m_doc); |
101 | } |
102 | |
103 | XmlNode XmlNode::FirstChild(const char* name) const |
104 | { |
105 | return XmlNode(m_node->FirstChildElement(name), *m_doc); |
106 | } |
107 | |
108 | XmlNode XmlNode::FirstChild(const Aws::String& name) const |
109 | { |
110 | return FirstChild(name.c_str()); |
111 | } |
112 | |
113 | bool XmlNode::HasChildren() const |
114 | { |
115 | return !m_node->NoChildren(); |
116 | } |
117 | |
118 | XmlNode XmlNode::Parent() const |
119 | { |
120 | return XmlNode(m_node->Parent()->ToElement(), *m_doc); |
121 | } |
122 | |
123 | Aws::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 | |
141 | void 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 | |
150 | XmlNode 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 | |
156 | XmlNode 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 | |
162 | bool XmlNode::IsNull() |
163 | { |
164 | return m_node == nullptr; |
165 | } |
166 | |
167 | static const char* XML_SERIALIZER_ALLOCATION_TAG = "XmlDocument" ; |
168 | |
169 | XmlDocument::XmlDocument() |
170 | { |
171 | m_doc = Aws::New<Aws::External::tinyxml2::XMLDocument>(XML_SERIALIZER_ALLOCATION_TAG, true, Aws::External::tinyxml2::Whitespace::PRESERVE_WHITESPACE); |
172 | } |
173 | |
174 | XmlDocument::XmlDocument(XmlDocument&& doc) : m_doc{ doc.m_doc } // take the innards |
175 | { |
176 | doc.m_doc = nullptr; // leave nothing behind |
177 | } |
178 | |
179 | XmlDocument::~XmlDocument() |
180 | { |
181 | Aws::Delete(m_doc); |
182 | } |
183 | |
184 | XmlNode XmlDocument::GetRootElement() const |
185 | { |
186 | return XmlNode(m_doc->FirstChildElement(), *this); |
187 | } |
188 | |
189 | bool XmlDocument::WasParseSuccessful() const |
190 | { |
191 | return !m_doc->Error(); |
192 | } |
193 | |
194 | Aws::String XmlDocument::GetErrorMessage() const |
195 | { |
196 | return !WasParseSuccessful() ? m_doc->ErrorName() : "" ; |
197 | } |
198 | |
199 | Aws::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 | |
208 | XmlDocument XmlDocument::CreateFromXmlStream(Aws::IOStream& xmlStream) |
209 | { |
210 | Aws::String xmlString((Aws::IStreamBufIterator(xmlStream)), Aws::IStreamBufIterator()); |
211 | return CreateFromXmlString(xmlString); |
212 | } |
213 | |
214 | XmlDocument 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 | |
221 | XmlDocument 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 | |