Line data Source code
1 : // file : xsd/cxx/xml/dom/serialization-source.txx
2 : // copyright : Copyright (c) 2005-2017 Code Synthesis Tools CC
3 : // license : GNU GPL v2 + exceptions; see accompanying LICENSE file
4 :
5 : #include <xercesc/util/XMLUni.hpp> // xercesc::fg*
6 : #include <xercesc/util/XMLUniDefs.hpp> // chLatin_L, etc
7 : #include <xercesc/validators/schema/SchemaSymbols.hpp>
8 :
9 : #include <xercesc/dom/DOMLSOutput.hpp>
10 : #include <xercesc/dom/DOMLSSerializer.hpp>
11 :
12 : #include <xercesc/dom/DOMElement.hpp>
13 : #include <xercesc/dom/DOMImplementation.hpp>
14 : #include <xercesc/dom/DOMImplementationRegistry.hpp>
15 :
16 : #include <xsd/cxx/xml/string.hxx>
17 : #include <xsd/cxx/xml/bits/literals.hxx>
18 : #include <xsd/cxx/xml/dom/bits/error-handler-proxy.hxx>
19 :
20 : namespace xsd
21 : {
22 : namespace cxx
23 : {
24 : namespace xml
25 : {
26 : namespace dom
27 : {
28 : //
29 : //
30 : template <typename C>
31 : xercesc::DOMAttr&
32 0 : create_attribute (const C* name, xercesc::DOMElement& parent)
33 : {
34 0 : xercesc::DOMDocument* doc (parent.getOwnerDocument ());
35 0 : xercesc::DOMAttr* a (doc->createAttribute (string (name).c_str ()));
36 0 : parent.setAttributeNode (a);
37 0 : return *a;
38 : }
39 :
40 : template <typename C>
41 : xercesc::DOMAttr&
42 : create_attribute (const C* name,
43 : const C* ns,
44 : xercesc::DOMElement& parent)
45 : {
46 : if (ns[0] == C ('\0'))
47 : return create_attribute (name, parent);
48 :
49 : xercesc::DOMDocument* doc (parent.getOwnerDocument ());
50 :
51 : xercesc::DOMAttr* a;
52 : std::basic_string<C> p (prefix<C> (ns, parent));
53 :
54 : if (!p.empty ())
55 : {
56 : p += ':';
57 : p += name;
58 : a = doc->createAttributeNS (string (ns).c_str (),
59 : string (p).c_str ());
60 : }
61 : else
62 : a = doc->createAttributeNS (string (ns).c_str (),
63 : string (name).c_str ());
64 :
65 : parent.setAttributeNodeNS (a);
66 : return *a;
67 : }
68 :
69 : template <typename C>
70 : xercesc::DOMElement&
71 0 : create_element (const C* name, xercesc::DOMElement& parent)
72 : {
73 0 : xercesc::DOMDocument* doc (parent.getOwnerDocument ());
74 0 : xercesc::DOMElement* e (doc->createElement (string (name).c_str ()));
75 0 : parent.appendChild (e);
76 0 : return *e;
77 : }
78 :
79 : template <typename C>
80 : xercesc::DOMElement&
81 : create_element (const C* name,
82 : const C* ns,
83 : xercesc::DOMElement& parent)
84 : {
85 : if (ns[0] == C ('\0'))
86 : return create_element (name, parent);
87 :
88 : xercesc::DOMDocument* doc (parent.getOwnerDocument ());
89 :
90 : xercesc::DOMElement* e;
91 : std::basic_string<C> p (prefix<C> (ns, parent));
92 :
93 : if (!p.empty ())
94 : {
95 : p += ':';
96 : p += name;
97 : e = doc->createElementNS (string (ns).c_str (),
98 : string (p).c_str ());
99 : }
100 : else
101 : e = doc->createElementNS (string (ns).c_str (),
102 : string (name).c_str ());
103 :
104 : parent.appendChild (e);
105 : return *e;
106 : }
107 :
108 : template <typename C>
109 : void
110 0 : add_namespaces (xercesc::DOMElement& el,
111 : const namespace_infomap<C>& map)
112 : {
113 : using namespace xercesc;
114 :
115 : typedef std::basic_string<C> string;
116 : typedef namespace_infomap<C> infomap;
117 : typedef typename infomap::const_iterator infomap_iterator;
118 :
119 0 : C colon (':'), space (' ');
120 :
121 : // Check if we need to provide xsi mapping.
122 : //
123 0 : bool xsi (false);
124 0 : string xsi_prefix;
125 0 : string xmlns_prefix (xml::bits::xmlns_prefix<C> ());
126 :
127 0 : for (infomap_iterator i (map.begin ()), e (map.end ()); i != e; ++i)
128 : {
129 0 : if (!i->second.schema.empty ())
130 : {
131 0 : xsi = true;
132 0 : break;
133 : }
134 : }
135 :
136 : // Check if we were told to provide xsi mapping.
137 : //
138 0 : if (xsi)
139 : {
140 0 : for (infomap_iterator i (map.begin ()), e (map.end ());
141 0 : i != e;
142 0 : ++i)
143 : {
144 0 : if (i->second.name == xml::bits::xsi_namespace<C> ())
145 : {
146 0 : xsi_prefix = i->first;
147 0 : xsi = false;
148 0 : break;
149 : }
150 : }
151 : }
152 :
153 : // Create user-defined mappings.
154 : //
155 0 : for (infomap_iterator i (map.begin ()), e (map.end ()); i != e; ++i)
156 : {
157 0 : if (i->first.empty ())
158 : {
159 : // Empty prefix.
160 : //
161 0 : if (!i->second.name.empty ())
162 0 : el.setAttributeNS (
163 : xercesc::XMLUni::fgXMLNSURIName,
164 0 : xml::string (xmlns_prefix).c_str (),
165 0 : xml::string (i->second.name).c_str ());
166 : }
167 : else
168 : {
169 0 : el.setAttributeNS (
170 : xercesc::XMLUni::fgXMLNSURIName,
171 0 : xml::string (xmlns_prefix + colon + i->first).c_str (),
172 0 : xml::string (i->second.name).c_str ());
173 : }
174 : }
175 :
176 : // If we were not told to provide xsi mapping but we need it
177 : // then we will have to add it ourselves.
178 : //
179 0 : if (xsi)
180 0 : xsi_prefix = dom::prefix (xml::bits::xsi_namespace<C> (),
181 : el,
182 : xml::bits::xsi_prefix<C> ());
183 :
184 : // Create xsi:schemaLocation and xsi:noNamespaceSchemaLocation
185 : // attributes.
186 : //
187 0 : string schema_location;
188 0 : string no_namespace_schema_location;
189 :
190 0 : for (infomap_iterator i (map.begin ()), e (map.end ()); i != e; ++i)
191 : {
192 0 : if (!i->second.schema.empty ())
193 : {
194 0 : if (i->second.name.empty ())
195 : {
196 0 : if (!no_namespace_schema_location.empty ())
197 0 : no_namespace_schema_location += space;
198 :
199 0 : no_namespace_schema_location += i->second.schema;
200 : }
201 : else
202 : {
203 0 : if (!schema_location.empty ())
204 0 : schema_location += space;
205 :
206 0 : schema_location += i->second.name + space + i->second.schema;
207 : }
208 : }
209 : }
210 :
211 0 : if (!schema_location.empty ())
212 : {
213 0 : el.setAttributeNS (
214 : xercesc::SchemaSymbols::fgURI_XSI,
215 0 : xml::string (xsi_prefix + colon +
216 : xml::bits::schema_location<C> ()).c_str (),
217 0 : xml::string (schema_location).c_str ());
218 : }
219 :
220 0 : if (!no_namespace_schema_location.empty ())
221 : {
222 0 : el.setAttributeNS (
223 : xercesc::SchemaSymbols::fgURI_XSI,
224 0 : xml::string (
225 : xsi_prefix + colon +
226 : xml::bits::no_namespace_schema_location<C> ()).c_str (),
227 0 : xml::string (no_namespace_schema_location).c_str ());
228 : }
229 0 : }
230 :
231 : //
232 : //
233 : template <typename C>
234 : XSD_DOM_AUTO_PTR<xercesc::DOMDocument>
235 0 : serialize (const std::basic_string<C>& el,
236 : const std::basic_string<C>& ns,
237 : const namespace_infomap<C>& map,
238 : unsigned long)
239 : {
240 : using namespace xercesc;
241 :
242 : typedef std::basic_string<C> string;
243 : typedef namespace_infomap<C> infomap;
244 : typedef typename infomap::const_iterator infomap_iterator;
245 :
246 0 : string prefix;
247 :
248 0 : if (!ns.empty ())
249 : {
250 0 : infomap_iterator i (map.begin ()), e (map.end ());
251 :
252 0 : for ( ;i != e; ++i)
253 : {
254 0 : if (i->second.name == ns)
255 : {
256 0 : prefix = i->first;
257 0 : break;
258 : }
259 : }
260 :
261 : // Since this is the first namespace in document we don't
262 : // need to worry about conflicts.
263 : //
264 0 : if (i == e)
265 0 : prefix = xml::bits::first_prefix<C> ();
266 : }
267 :
268 0 : const XMLCh ls[] = {xercesc::chLatin_L,
269 : xercesc::chLatin_S,
270 : xercesc::chNull};
271 :
272 : DOMImplementation* impl (
273 0 : DOMImplementationRegistry::getDOMImplementation (ls));
274 :
275 0 : XSD_DOM_AUTO_PTR<DOMDocument> doc (
276 0 : impl->createDocument (
277 0 : (ns.empty () ? 0 : xml::string (ns).c_str ()),
278 0 : xml::string ((prefix.empty ()
279 0 : ? el
280 : : prefix + C (':') + el)).c_str (),
281 : 0));
282 :
283 0 : add_namespaces (*doc->getDocumentElement (), map);
284 :
285 0 : return doc;
286 0 : }
287 :
288 :
289 : template <typename C>
290 : bool
291 0 : serialize (xercesc::XMLFormatTarget& target,
292 : const xercesc::DOMDocument& doc,
293 : const std::basic_string<C>& encoding,
294 : xercesc::DOMErrorHandler& eh,
295 : unsigned long flags)
296 : {
297 : using namespace xercesc;
298 :
299 0 : const XMLCh ls[] = {xercesc::chLatin_L,
300 : xercesc::chLatin_S,
301 : xercesc::chNull};
302 :
303 : DOMImplementation* impl (
304 0 : DOMImplementationRegistry::getDOMImplementation (ls));
305 :
306 0 : bits::error_handler_proxy<C> ehp (eh);
307 :
308 0 : XSD_DOM_AUTO_PTR<DOMLSSerializer> writer (
309 0 : impl->createLSSerializer ());
310 :
311 0 : DOMConfiguration* conf (writer->getDomConfig ());
312 :
313 0 : conf->setParameter (XMLUni::fgDOMErrorHandler, &ehp);
314 :
315 : // Set some nice features if the serializer supports them.
316 : //
317 0 : if (conf->canSetParameter (
318 : XMLUni::fgDOMWRTDiscardDefaultContent, true))
319 0 : conf->setParameter (XMLUni::fgDOMWRTDiscardDefaultContent, true);
320 :
321 0 : if (!(flags & dont_pretty_print) &&
322 0 : conf->canSetParameter (XMLUni::fgDOMWRTFormatPrettyPrint, true))
323 : {
324 0 : conf->setParameter (XMLUni::fgDOMWRTFormatPrettyPrint, true);
325 :
326 : // Don't add extra new lines between first-level elements.
327 : //
328 0 : if (conf->canSetParameter (XMLUni::fgDOMWRTXercesPrettyPrint, true))
329 0 : conf->setParameter (XMLUni::fgDOMWRTXercesPrettyPrint, false);
330 : }
331 :
332 : // See if we need to write XML declaration.
333 : //
334 0 : if ((flags & no_xml_declaration) &&
335 0 : conf->canSetParameter (XMLUni::fgDOMXMLDeclaration, false))
336 0 : conf->setParameter (XMLUni::fgDOMXMLDeclaration, false);
337 :
338 0 : XSD_DOM_AUTO_PTR<DOMLSOutput> out (impl->createLSOutput ());
339 :
340 0 : out->setEncoding (xml::string (encoding).c_str ());
341 0 : out->setByteStream (&target);
342 :
343 0 : if (!writer->write (&doc, out.get ()) || ehp.failed ())
344 0 : return false;
345 :
346 0 : return true;
347 0 : }
348 :
349 : template <typename C>
350 : bool
351 0 : serialize (xercesc::XMLFormatTarget& target,
352 : const xercesc::DOMDocument& doc,
353 : const std::basic_string<C>& enconding,
354 : error_handler<C>& eh,
355 : unsigned long flags)
356 : {
357 0 : bits::error_handler_proxy<C> ehp (eh);
358 0 : return serialize (target, doc, enconding, ehp, flags);
359 0 : }
360 : }
361 : }
362 : }
363 : }
|