1 /*
2 * Copyright (C) 2019 Google Inc.
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 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "xmlProtoConverter.h"
18
19 #include <algorithm>
20
21 using namespace std;
22 using namespace xmlProtoFuzzer;
23
removeNonAscii(string const & _utf8)24 string ProtoConverter::removeNonAscii(string const& _utf8)
25 {
26 string asciiStr{_utf8};
27 asciiStr.erase(remove_if(asciiStr.begin(), asciiStr.end(), [=](char c) -> bool {
28 return !(std::isalpha(c) || std::isdigit(c));
29 }), asciiStr.end());
30 return asciiStr.empty() ? "fuzz" : asciiStr;
31 }
32
33
visit(Misc const & _x)34 void ProtoConverter::visit(Misc const& _x)
35 {
36 switch (_x.misc_oneof_case())
37 {
38 case Misc::kComment:
39 m_output << "<!--" << _x.comment() << "-->\n";
40 break;
41 case Misc::kInst:
42 visit(_x.inst());
43 break;
44 case Misc::MISC_ONEOF_NOT_SET:
45 break;
46 }
47 }
48
visit(Prolog const & _x)49 void ProtoConverter::visit(Prolog const& _x)
50 {
51 visit(_x.decl());
52 visit(_x.doctype());
53 for (auto const& misc: _x.misc())
54 visit(misc);
55 }
56
visit(KeyValue const & _x)57 void ProtoConverter::visit(KeyValue const& _x)
58 {
59 if (!KeyValue::XmlNamespace_IsValid(_x.type()))
60 return;
61
62 switch (_x.type())
63 {
64 case KeyValue::ATTRIBUTES:
65 m_output << "xml:attributes=\"" << removeNonAscii(_x.value()) << "\" ";
66 break;
67 case KeyValue::BASE:
68 m_output << "xml:base=\"" << removeNonAscii(_x.value()) << "\" ";
69 break;
70 case KeyValue::CATALOG:
71 m_output << "xml:catalog=\"" << removeNonAscii(_x.value()) << "\" ";
72 break;
73 case KeyValue::ID:
74 m_output << "xml:id=\"" << removeNonAscii(_x.value()) << "\" ";
75 break;
76 case KeyValue::LANG:
77 m_output << "xml:lang=\"" << removeNonAscii(_x.value()) << "\" ";
78 break;
79 case KeyValue::LINK:
80 m_output << "xml:link=\"" << removeNonAscii(_x.value()) << "\" ";
81 break;
82 case KeyValue::SPACE:
83 m_output << "xml:space=\"" << removeNonAscii(_x.value()) << "\" ";
84 break;
85 case KeyValue::SPECIAL:
86 m_output << "xml:special=\"" << removeNonAscii(_x.value()) << "\" ";
87 break;
88 case KeyValue::TEST:
89 m_output << "xml:test=\"" << removeNonAscii(_x.value()) << "\" ";
90 break;
91 case KeyValue::FUZZ:
92 if (_x.ByteSizeLong() % 2)
93 m_output << "xmlns:" << removeNonAscii(_x.key()) << "=\"" << removeNonAscii(_x.value()) << "\" ";
94 else
95 m_output << removeNonAscii(_x.key()) << "=\"" << removeNonAscii(_x.value()) << "\" ";
96 break;
97 case KeyValue_XmlNamespace_KeyValue_XmlNamespace_INT_MIN_SENTINEL_DO_NOT_USE_:
98 case KeyValue_XmlNamespace_KeyValue_XmlNamespace_INT_MAX_SENTINEL_DO_NOT_USE_:
99 break;
100 }
101 }
102
visit(ProcessingInstruction const & _x)103 void ProtoConverter::visit(ProcessingInstruction const& _x)
104 {
105 m_output << "<?" << removeNonAscii(_x.name()) << " ";
106 for (auto const& prop: _x.kv())
107 visit(prop);
108 m_output << "?>\n";
109 }
110
visit(Content const & _x)111 void ProtoConverter::visit(Content const& _x)
112 {
113 switch (_x.content_oneof_case())
114 {
115 case Content::kStr:
116 m_output << _x.str() << "\n";
117 break;
118 case Content::kE:
119 visit(_x.e());
120 m_output << "\n";
121 break;
122 case Content::kC:
123 visit(_x.c());
124 m_output << "\n";
125 break;
126 case Content::CONTENT_ONEOF_NOT_SET:
127 break;
128 }
129 }
130
visit(ElementDecl const & _x)131 void ProtoConverter::visit(ElementDecl const& _x)
132 {
133 if (!ElementDecl::ContentSpec_IsValid(_x.spec()))
134 return;
135
136 m_output << "<!ELEMENT " << _x.name() << " ";
137 switch (_x.spec())
138 {
139 case ElementDecl::EMPTY:
140 m_output << "EMPTY>";
141 break;
142 case ElementDecl::ANY:
143 m_output << "ANY>";
144 break;
145 case ElementDecl::FUZZ:
146 m_output << "FUZZ>";
147 break;
148 case ElementDecl::MIXED:
149 m_output << "(#PCDATA";
150 for (auto const& pcdata: _x.cdata())
151 m_output << "|" << pcdata;
152 m_output << ")";
153 if (_x.cdata_size() > 0)
154 m_output << "*";
155 m_output << ">";
156 break;
157 case ElementDecl::CHILDREN:
158 {
159 m_output << "(";
160 string delim = "";
161 for (auto const& str: _x.cdata()) {
162 m_output << delim << removeNonAscii(str);
163 delim = ", ";
164 }
165 m_output << ")>";
166 break;
167 }
168 case ElementDecl_ContentSpec_ElementDecl_ContentSpec_INT_MIN_SENTINEL_DO_NOT_USE_:
169 case ElementDecl_ContentSpec_ElementDecl_ContentSpec_INT_MAX_SENTINEL_DO_NOT_USE_:
170 break;
171 }
172 }
173
visit(AttValue const & _x)174 void ProtoConverter::visit(AttValue const& _x)
175 {
176 if (!isValid(_x))
177 return;
178
179 m_output << "\"";
180 string prefix;
181 switch (_x.type())
182 {
183 case AttValue::ENTITY:
184 prefix = "&";
185 break;
186 case AttValue::CHAR:
187 if (_x.ByteSizeLong() % 2)
188 prefix = "&#";
189 else
190 // TODO: Value that follows this must be a
191 // sequence of hex digits.
192 prefix = "&#x";
193 break;
194 case AttValue::FUZZ:
195 prefix = "fuzz";
196 break;
197 case AttValue_Type_AttValue_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
198 case AttValue_Type_AttValue_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
199 break;
200 }
201 for (auto const& name: _x.value())
202 m_output << prefix << removeNonAscii(name) << ";";
203 m_output << "\"";
204 }
205
visit(DefaultDecl const & _x)206 void ProtoConverter::visit(DefaultDecl const& _x)
207 {
208 if (!isValid(_x))
209 return;
210
211 switch (_x.type())
212 {
213 case DefaultDecl::REQUIRED:
214 m_output << "#REQUIRED";
215 break;
216 case DefaultDecl::IMPLIED:
217 m_output << "#IMPLIED";
218 break;
219 case DefaultDecl::FIXED:
220 m_output << "#FIXED ";
221 visit(_x.att());
222 break;
223 case DefaultDecl::FUZZ:
224 m_output << "#FUZZ";
225 break;
226 case DefaultDecl_Type_DefaultDecl_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
227 case DefaultDecl_Type_DefaultDecl_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
228 break;
229 }
230 }
231
visit(AttDef const & _x)232 void ProtoConverter::visit(AttDef const& _x)
233 {
234 if (!isValid(_x))
235 return;
236
237 m_output << " " << removeNonAscii(_x.name()) << " ";
238 switch (_x.type())
239 {
240 case AttDef::CDATA:
241 m_output << "CDATA ";
242 break;
243 case AttDef::ID:
244 m_output << "ID ";
245 break;
246 case AttDef::IDREF:
247 m_output << "IDREF ";
248 break;
249 case AttDef::IDREFS:
250 m_output << "IDREFS ";
251 break;
252 case AttDef::ENTITY:
253 m_output << "ENTITY ";
254 break;
255 case AttDef::ENTITIES:
256 m_output << "ENTITIES ";
257 break;
258 case AttDef::NMTOKEN:
259 m_output << "NMTOKEN ";
260 break;
261 case AttDef::NMTOKENS:
262 m_output << "NMTOKENS ";
263 break;
264 case AttDef::FUZZ:
265 m_output << "FUZZ ";
266 break;
267 case AttDef_Type_AttDef_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
268 case AttDef_Type_AttDef_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
269 break;
270 }
271 visit(_x.def());
272 }
273
visit(AttListDecl const & _x)274 void ProtoConverter::visit(AttListDecl const& _x)
275 {
276 m_output << "<!ATTLIST " << removeNonAscii(_x.name());
277 for (auto const& att: _x.attdefs())
278 visit(att);
279 m_output << ">";
280 }
281
visit(NotationDecl const & _x)282 void ProtoConverter::visit(NotationDecl const& _x)
283 {
284 m_output << "<!NOTATION " << removeNonAscii(_x.name()) << " ";
285 switch (_x.notation_oneof_case())
286 {
287 case NotationDecl::kExt:
288 visit(_x.ext());
289 break;
290 case NotationDecl::kPub:
291 m_output << "PUBLIC " << _x.pub();
292 break;
293 case NotationDecl::kFuzz:
294 m_output << "FUZZ " << _x.fuzz();
295 break;
296 case NotationDecl::NOTATION_ONEOF_NOT_SET:
297 break;
298 }
299 m_output << ">";
300 }
301
visit(NDataDecl const & _x)302 void ProtoConverter::visit(NDataDecl const& _x)
303 {
304 m_output << " NDATA " << _x.name();
305 }
306
visit(EntityDef const & _x)307 void ProtoConverter::visit(EntityDef const& _x)
308 {
309 switch (_x.entity_oneof_case())
310 {
311 case EntityDef::kExt:
312 visit(_x.ext());
313 if (_x.ByteSizeLong() % 2)
314 visit(_x.ndata());
315 break;
316 case EntityDef::kVal:
317 visit(_x.val());
318 break;
319 case EntityDef::ENTITY_ONEOF_NOT_SET:
320 break;
321 }
322 }
323
visit(PEDef const & _x)324 void ProtoConverter::visit(PEDef const& _x)
325 {
326 switch (_x.pedef_oneof_case())
327 {
328 case PEDef::kVal:
329 visit(_x.val());
330 break;
331 case PEDef::kId:
332 visit(_x.id());
333 break;
334 case PEDef::PEDEF_ONEOF_NOT_SET:
335 break;
336 }
337 }
338
visit(EntityValue const & _x)339 void ProtoConverter::visit(EntityValue const& _x)
340 {
341 if (!isValid(_x))
342 return;
343
344 m_output << "\"";
345 string prefix;
346 switch (_x.type())
347 {
348 case EntityValue::ENTITY:
349 prefix = "&";
350 break;
351 case EntityValue::CHAR:
352 if (_x.ByteSizeLong() % 2)
353 prefix = "&#";
354 else
355 prefix = "&#x";
356 break;
357 case EntityValue::PEREF:
358 prefix = "%";
359 break;
360 case EntityValue::FUZZ:
361 prefix = "fuzz";
362 break;
363 case EntityValue_Type_EntityValue_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
364 case EntityValue_Type_EntityValue_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
365 break;
366 }
367 for (auto const& ref: _x.name())
368 m_output << prefix << ref << ";";
369 m_output << "\"";
370 }
371
visit(EntityDecl const & _x)372 void ProtoConverter::visit(EntityDecl const& _x)
373 {
374 if (!isValid(_x))
375 return;
376
377 m_output << "<!ENTITY ";
378 switch (_x.type())
379 {
380 case EntityDecl::GEDECL:
381 m_output << _x.name() << " ";
382 visit(_x.ent());
383 break;
384 case EntityDecl::PEDECL:
385 m_output << "% " << _x.name() << " ";
386 visit(_x.pedef());
387 break;
388 case EntityDecl_Type_EntityDecl_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
389 case EntityDecl_Type_EntityDecl_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
390 break;
391 }
392 m_output << ">";
393 }
394
visit(ConditionalSect const & _x)395 void ProtoConverter::visit(ConditionalSect const& _x)
396 {
397 if (!isValid(_x))
398 return;
399
400 switch (_x.type())
401 {
402 case ConditionalSect::INCLUDE:
403 m_output << "<![ INCLUDE [";
404 visit(_x.ext());
405 m_output << "]]>";
406 break;
407 case ConditionalSect::IGNORE:
408 m_output << "<![ IGNORE [";
409 for (auto const& str: _x.ignores())
410 m_output << "<![" << removeNonAscii(str) << "]]>";
411 m_output << "]]>";
412 break;
413 case ConditionalSect::FUZZ:
414 m_output << "<![ FUZZ [";
415 visit(_x.ext());
416 m_output << "]]>";
417 break;
418 case ConditionalSect_Type_ConditionalSect_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
419 case ConditionalSect_Type_ConditionalSect_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
420 break;
421 }
422 }
423
424
visit(OneExtSubsetDecl const & _x)425 void ProtoConverter::visit(OneExtSubsetDecl const& _x)
426 {
427 switch (_x.extsubset_oneof_case())
428 {
429 case OneExtSubsetDecl::kM:
430 visit(_x.m());
431 break;
432 case OneExtSubsetDecl::kC:
433 visit(_x.c());
434 break;
435 case OneExtSubsetDecl::EXTSUBSET_ONEOF_NOT_SET:
436 break;
437 }
438 }
439
440
visit(ExtSubsetDecl const & _x)441 void ProtoConverter::visit(ExtSubsetDecl const& _x)
442 {
443 for (auto const& decl: _x.decls())
444 visit(decl);
445 }
446
visit(CData const & _x)447 void ProtoConverter::visit(CData const& _x)
448 {
449 m_output << "<![CDATA[" << removeNonAscii(_x.data()) << "]]>";
450 }
451
visit(MarkupDecl const & _x)452 void ProtoConverter::visit(MarkupDecl const& _x)
453 {
454 switch (_x.markup_oneof_case())
455 {
456 case MarkupDecl::kE:
457 visit(_x.e());
458 break;
459 case MarkupDecl::kA:
460 visit(_x.a());
461 break;
462 case MarkupDecl::kN:
463 visit(_x.n());
464 break;
465 case MarkupDecl::kM:
466 visit(_x.m());
467 break;
468 case MarkupDecl::kEntity:
469 visit(_x.entity());
470 break;
471 case MarkupDecl::kExt:
472 visit(_x.ext());
473 break;
474 case MarkupDecl::MARKUP_ONEOF_NOT_SET:
475 break;
476 }
477 }
478
479 /// Returns predefined element from an Element_Id enum
480 /// @param _x is an enum that holds the desired type of predefined value
481 /// @param _prop is a string that holds the value of the desired type
482 /// @return string holding the predefined value of the form
483 /// name attribute=\"value\"
getPredefined(Element_Id _x,string const & _prop)484 string ProtoConverter::getPredefined(Element_Id _x, string const& _prop)
485 {
486 string output{};
487 switch (_x)
488 {
489 case Element::XIINCLUDE:
490 case Element::XIFALLBACK:
491 case Element::XIHREF:
492 output = "xi:include href=\"fuzz.xml\"";
493 case Element::XIPARSE:
494 output = "xi:include parse=\"xml\"";
495 case Element::XIXPOINTER:
496 output = "xi:include xpointer=\"" + removeNonAscii(_prop) + "\"";
497 case Element::XIENCODING:
498 output = "xi:include encoding=\"" + removeNonAscii(_prop) + "\"";
499 case Element::XIACCEPT:
500 output = "xi:include accept=\"" + removeNonAscii(_prop) + "\"";
501 case Element::XIACCEPTLANG:
502 output = "xi:include accept-language=\"" + removeNonAscii(_prop) + "\"";
503 case Element_Id_Element_Id_INT_MIN_SENTINEL_DO_NOT_USE_:
504 case Element_Id_Element_Id_INT_MAX_SENTINEL_DO_NOT_USE_:
505 output = "xi:fuzz xifuzz=\"fuzz\"";
506 }
507 return output;
508 }
509
510 /// Returns uri string for a given Element_Id type
getUri(Element_Id _x)511 string ProtoConverter::getUri(Element_Id _x)
512 {
513 if (!Element::Id_IsValid(_x))
514 return s_XInclude;
515
516 switch (_x)
517 {
518 case Element::XIINCLUDE:
519 case Element::XIFALLBACK:
520 case Element::XIHREF:
521 case Element::XIPARSE:
522 case Element::XIXPOINTER:
523 case Element::XIENCODING:
524 case Element::XIACCEPT:
525 case Element::XIACCEPTLANG:
526 case Element_Id_Element_Id_INT_MIN_SENTINEL_DO_NOT_USE_:
527 case Element_Id_Element_Id_INT_MAX_SENTINEL_DO_NOT_USE_:
528 return s_XInclude;
529 }
530 }
531
visit(Element const & _x)532 void ProtoConverter::visit(Element const& _x)
533 {
534 if (!isValid(_x))
535 return;
536
537 // Predefined child node
538 string child = {};
539 // Predefined uri for child node
540 string pUri = {};
541 // Element name
542 string name = removeNonAscii(_x.name());
543
544 switch (_x.type())
545 {
546 case Element::PREDEFINED:
547 child = getPredefined(_x.id(), _x.childprop());
548 pUri = getUri(_x.id());
549 break;
550 case Element::FUZZ:
551 case Element_Type_Element_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
552 case Element_Type_Element_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
553 break;
554 }
555
556 // <name k1=v1 k2=v2 k3=v3>
557 // <content>
558 // </name>
559
560 // Start name tag: Must be Ascii?
561 m_output << "<" << name << " ";
562
563 // Add uri to name tag
564 if (!pUri.empty())
565 m_output << pUri << " ";
566 for (auto const& prop: _x.kv())
567 visit(prop);
568 m_output << ">\n";
569
570 // Add attribute
571 if (!child.empty())
572 m_output << "<" << child << "/>\n";
573
574 // Add content
575 visit(_x.content());
576
577 // Close name tag
578 m_output << "</" << name << ">\n";
579 }
580
visit(ExternalId const & _x)581 void ProtoConverter::visit(ExternalId const& _x)
582 {
583 if (!isValid(_x))
584 return;
585
586 switch (_x.type())
587 {
588 case ExternalId::SYSTEM:
589 m_output << "SYSTEM " << "\"" << removeNonAscii(_x.system()) << "\"";
590 break;
591 case ExternalId::PUBLIC:
592 m_output << "PUBLIC " << "\"" << removeNonAscii(_x.pub()) << "\""
593 << " " << "\"" << removeNonAscii(_x.system()) << "\"";
594 break;
595 case ExternalId::FUZZ:
596 m_output << "FUZZ " << "\"" << removeNonAscii(_x.pub()) << "\"";
597 break;
598 case ExternalId_Type_ExternalId_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
599 case ExternalId_Type_ExternalId_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
600 break;
601 }
602 }
603
visit(DocTypeDecl const & _x)604 void ProtoConverter::visit(DocTypeDecl const& _x)
605 {
606 m_output << "<!DOCTYPE " << removeNonAscii(_x.name()) << " ";
607 visit(_x.ext());
608 m_output << "[";
609 for (auto const& m: _x.mdecl())
610 visit(m);
611 m_output << "]";
612 m_output << ">\n";
613 }
614
visit(VersionNum const & _x)615 void ProtoConverter::visit(VersionNum const& _x)
616 {
617 if (!isValid(_x))
618 return;
619
620 switch (_x.type())
621 {
622 case VersionNum::STANDARD:
623 m_output << "\"1.0\"";
624 break;
625 case VersionNum::FUZZ:
626 case VersionNum_Type_VersionNum_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
627 case VersionNum_Type_VersionNum_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
628 m_output << "\"" << _x.major() << "." << _x.minor() << "\"";
629 break;
630 }
631 }
632
visit(Encodings const & _x)633 void ProtoConverter::visit(Encodings const& _x)
634 {
635 if (!Encodings::Enc_IsValid(_x.name()))
636 return;
637
638 m_output << " encoding=\"";
639 switch (_x.name())
640 {
641 case Encodings::BIG5:
642 m_output << "BIG5";
643 break;
644 case Encodings::EUCJP:
645 m_output << "EUC-JP";
646 break;
647 case Encodings::EUCKR:
648 m_output << "EUC-KR";
649 break;
650 case Encodings::GB18030:
651 m_output << "GB18030";
652 break;
653 case Encodings::ISO2022JP:
654 m_output << "ISO-2022-JP";
655 break;
656 case Encodings::ISO2022KR:
657 m_output << "ISO-2022-KR";
658 break;
659 case Encodings::ISO88591:
660 m_output << "ISO-8859-1";
661 break;
662 case Encodings::ISO88592:
663 m_output << "ISO-8859-2";
664 break;
665 case Encodings::ISO88593:
666 m_output << "ISO-8859-3";
667 break;
668 case Encodings::ISO88594:
669 m_output << "ISO-8859-4";
670 break;
671 case Encodings::ISO88595:
672 m_output << "ISO-8859-5";
673 break;
674 case Encodings::ISO88596:
675 m_output << "ISO-8859-6";
676 break;
677 case Encodings::ISO88597:
678 m_output << "ISO-8859-7";
679 break;
680 case Encodings::ISO88598:
681 m_output << "ISO-8859-8";
682 break;
683 case Encodings::ISO88599:
684 m_output << "ISO-8859-9";
685 break;
686 case Encodings::SHIFTJIS:
687 m_output << "SHIFT_JIS";
688 break;
689 case Encodings::TIS620:
690 m_output << "TIS-620";
691 break;
692 case Encodings::USASCII:
693 m_output << "US-ASCII";
694 break;
695 case Encodings::UTF8:
696 m_output << "UTF-8";
697 break;
698 case Encodings::UTF16:
699 m_output << "UTF-16";
700 break;
701 case Encodings::UTF16BE:
702 m_output << "UTF-16BE";
703 break;
704 case Encodings::UTF16LE:
705 m_output << "UTF-16LE";
706 break;
707 case Encodings::WINDOWS31J:
708 m_output << "WINDOWS-31J";
709 break;
710 case Encodings::WINDOWS1255:
711 m_output << "WINDOWS-1255";
712 break;
713 case Encodings::WINDOWS1256:
714 m_output << "WINDOWS-1256";
715 break;
716 case Encodings::FUZZ:
717 m_output << removeNonAscii(_x.fuzz());
718 break;
719 case Encodings_Enc_Encodings_Enc_INT_MIN_SENTINEL_DO_NOT_USE_:
720 case Encodings_Enc_Encodings_Enc_INT_MAX_SENTINEL_DO_NOT_USE_:
721 break;
722 }
723 m_output << "\"";
724 }
725
visit(XmlDeclaration const & _x)726 void ProtoConverter::visit(XmlDeclaration const& _x)
727 {
728 m_output << R"(<?xml version=)";
729 visit(_x.ver());
730 visit(_x.enc());
731 switch (_x.standalone())
732 {
733 case XmlDeclaration::YES:
734 m_output << " standalone=\'yes\'";
735 break;
736 case XmlDeclaration::NO:
737 m_output << " standalone=\'no\'";
738 break;
739 case XmlDeclaration_Standalone_XmlDeclaration_Standalone_INT_MIN_SENTINEL_DO_NOT_USE_:
740 case XmlDeclaration_Standalone_XmlDeclaration_Standalone_INT_MAX_SENTINEL_DO_NOT_USE_:
741 default:
742 break;
743 }
744 m_output << "?>\n";
745 }
746
visit(XmlDocument const & _x)747 void ProtoConverter::visit(XmlDocument const& _x)
748 {
749 visit(_x.p());
750 for (auto const& element: _x.e())
751 visit(element);
752 }
753
protoToString(XmlDocument const & _x)754 string ProtoConverter::protoToString(XmlDocument const& _x)
755 {
756 visit(_x);
757 return m_output.str();
758 }
759