xref: /aosp_15_r20/external/libprotobuf-mutator/examples/xml/xml_writer.cc (revision fd525a9c096e28cf6f8d8719388df0568a611e7b)
1*fd525a9cSAndroid Build Coastguard Worker // Copyright 2017 Google Inc. All rights reserved.
2*fd525a9cSAndroid Build Coastguard Worker //
3*fd525a9cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*fd525a9cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*fd525a9cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*fd525a9cSAndroid Build Coastguard Worker //
7*fd525a9cSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*fd525a9cSAndroid Build Coastguard Worker //
9*fd525a9cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*fd525a9cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*fd525a9cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*fd525a9cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*fd525a9cSAndroid Build Coastguard Worker // limitations under the License.
14*fd525a9cSAndroid Build Coastguard Worker 
15*fd525a9cSAndroid Build Coastguard Worker #include "examples/xml/xml_writer.h"
16*fd525a9cSAndroid Build Coastguard Worker 
17*fd525a9cSAndroid Build Coastguard Worker #include <algorithm>
18*fd525a9cSAndroid Build Coastguard Worker #include <sstream>
19*fd525a9cSAndroid Build Coastguard Worker 
20*fd525a9cSAndroid Build Coastguard Worker #include "examples/xml/xml.pb.h"
21*fd525a9cSAndroid Build Coastguard Worker 
22*fd525a9cSAndroid Build Coastguard Worker namespace protobuf_mutator {
23*fd525a9cSAndroid Build Coastguard Worker namespace xml {
24*fd525a9cSAndroid Build Coastguard Worker 
25*fd525a9cSAndroid Build Coastguard Worker namespace {
26*fd525a9cSAndroid Build Coastguard Worker 
27*fd525a9cSAndroid Build Coastguard Worker class XmlWriter {
28*fd525a9cSAndroid Build Coastguard Worker  public:
29*fd525a9cSAndroid Build Coastguard Worker   XmlWriter();
30*fd525a9cSAndroid Build Coastguard Worker   std::string ToXml(const Document& doc);
31*fd525a9cSAndroid Build Coastguard Worker 
32*fd525a9cSAndroid Build Coastguard Worker  private:
33*fd525a9cSAndroid Build Coastguard Worker   void ToXml(const std::string& name, const std::string& value);
34*fd525a9cSAndroid Build Coastguard Worker   void ToXml(const Element& element);
35*fd525a9cSAndroid Build Coastguard Worker   void ToXml(const Content& content);
36*fd525a9cSAndroid Build Coastguard Worker   void ToXml(const Misk& misk);
37*fd525a9cSAndroid Build Coastguard Worker   void ToXml(const DoctypeDecl& doctype);
38*fd525a9cSAndroid Build Coastguard Worker 
39*fd525a9cSAndroid Build Coastguard Worker   std::ostringstream out_;
40*fd525a9cSAndroid Build Coastguard Worker };
41*fd525a9cSAndroid Build Coastguard Worker 
XmlWriter()42*fd525a9cSAndroid Build Coastguard Worker XmlWriter::XmlWriter() {}
43*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const std::string & name,const std::string & value)44*fd525a9cSAndroid Build Coastguard Worker void XmlWriter::ToXml(const std::string& name, const std::string& value) {
45*fd525a9cSAndroid Build Coastguard Worker   char quote = (name.size() % 2) ? '"' : '\'';
46*fd525a9cSAndroid Build Coastguard Worker   out_ << " " << name << "=" << quote << value << quote;
47*fd525a9cSAndroid Build Coastguard Worker }
48*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const Misk & misk)49*fd525a9cSAndroid Build Coastguard Worker void XmlWriter::ToXml(const Misk& misk) {
50*fd525a9cSAndroid Build Coastguard Worker   if (misk.has_pi()) {
51*fd525a9cSAndroid Build Coastguard Worker     out_ << "<?" << misk.pi().target() << misk.pi().data() << "?>";
52*fd525a9cSAndroid Build Coastguard Worker   }
53*fd525a9cSAndroid Build Coastguard Worker 
54*fd525a9cSAndroid Build Coastguard Worker   if (misk.has_comment()) {
55*fd525a9cSAndroid Build Coastguard Worker     out_ << "<!--" << misk.comment() << "-->";
56*fd525a9cSAndroid Build Coastguard Worker   }
57*fd525a9cSAndroid Build Coastguard Worker }
58*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const DoctypeDecl & doctype)59*fd525a9cSAndroid Build Coastguard Worker void XmlWriter::ToXml(const DoctypeDecl& doctype) {
60*fd525a9cSAndroid Build Coastguard Worker   out_ << "<!DOCTYPE " << doctype.name();
61*fd525a9cSAndroid Build Coastguard Worker   if (doctype.has_external_id()) out_ << " " << doctype.external_id();
62*fd525a9cSAndroid Build Coastguard Worker   if (doctype.has_int_subset()) out_ << " [" << doctype.int_subset() << "]";
63*fd525a9cSAndroid Build Coastguard Worker   for (int i = 0; i < doctype.misk_size(); ++i) ToXml(doctype.misk(i));
64*fd525a9cSAndroid Build Coastguard Worker   out_ << ">";
65*fd525a9cSAndroid Build Coastguard Worker }
66*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const Content & content)67*fd525a9cSAndroid Build Coastguard Worker void XmlWriter::ToXml(const Content& content) {
68*fd525a9cSAndroid Build Coastguard Worker   if (content.has_char_data()) out_ << content.char_data();
69*fd525a9cSAndroid Build Coastguard Worker   if (content.has_element()) ToXml(content.element());
70*fd525a9cSAndroid Build Coastguard Worker   if (content.has_reference()) {
71*fd525a9cSAndroid Build Coastguard Worker     out_ << (content.reference().entry() ? '&' : '%')
72*fd525a9cSAndroid Build Coastguard Worker          << content.reference().name() << ';';
73*fd525a9cSAndroid Build Coastguard Worker   }
74*fd525a9cSAndroid Build Coastguard Worker   if (content.has_cdsect()) out_ << "<![CDATA[" << content.cdsect() << "]]>";
75*fd525a9cSAndroid Build Coastguard Worker 
76*fd525a9cSAndroid Build Coastguard Worker   if (content.has_misk()) ToXml(content.misk());
77*fd525a9cSAndroid Build Coastguard Worker }
78*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const Element & element)79*fd525a9cSAndroid Build Coastguard Worker void XmlWriter::ToXml(const Element& element) {
80*fd525a9cSAndroid Build Coastguard Worker   std::string tag;
81*fd525a9cSAndroid Build Coastguard Worker   std::string name;
82*fd525a9cSAndroid Build Coastguard Worker   tag += element.tag().name();
83*fd525a9cSAndroid Build Coastguard Worker   out_ << "<" << tag;
84*fd525a9cSAndroid Build Coastguard Worker 
85*fd525a9cSAndroid Build Coastguard Worker   for (int i = 0; i < element.tag().attribute_size(); ++i) {
86*fd525a9cSAndroid Build Coastguard Worker     ToXml(element.tag().attribute(i).name(),
87*fd525a9cSAndroid Build Coastguard Worker           element.tag().attribute(i).value());
88*fd525a9cSAndroid Build Coastguard Worker   }
89*fd525a9cSAndroid Build Coastguard Worker 
90*fd525a9cSAndroid Build Coastguard Worker   if (element.content_size() == 0) {
91*fd525a9cSAndroid Build Coastguard Worker     out_ << "/>";
92*fd525a9cSAndroid Build Coastguard Worker   } else {
93*fd525a9cSAndroid Build Coastguard Worker     out_ << ">";
94*fd525a9cSAndroid Build Coastguard Worker     for (int i = 0; i < element.content_size(); ++i) ToXml(element.content(i));
95*fd525a9cSAndroid Build Coastguard Worker     out_ << "</" << tag << ">";
96*fd525a9cSAndroid Build Coastguard Worker   }
97*fd525a9cSAndroid Build Coastguard Worker }
98*fd525a9cSAndroid Build Coastguard Worker 
ToXml(const Document & doc)99*fd525a9cSAndroid Build Coastguard Worker std::string XmlWriter::ToXml(const Document& doc) {
100*fd525a9cSAndroid Build Coastguard Worker   out_.str("");
101*fd525a9cSAndroid Build Coastguard Worker 
102*fd525a9cSAndroid Build Coastguard Worker   if (doc.has_version() || doc.has_encoding() || doc.has_standalone()) {
103*fd525a9cSAndroid Build Coastguard Worker     out_ << "<?xml";
104*fd525a9cSAndroid Build Coastguard Worker     if (doc.has_version())
105*fd525a9cSAndroid Build Coastguard Worker       ToXml("version", (doc.version().size() == 7) ? "1.0" : doc.version());
106*fd525a9cSAndroid Build Coastguard Worker     if (doc.has_encoding()) ToXml("encoding", doc.encoding());
107*fd525a9cSAndroid Build Coastguard Worker     if (doc.has_standalone())
108*fd525a9cSAndroid Build Coastguard Worker       ToXml("encoding", doc.standalone() ? "yes" : "no");
109*fd525a9cSAndroid Build Coastguard Worker     out_ << "?>";
110*fd525a9cSAndroid Build Coastguard Worker   }
111*fd525a9cSAndroid Build Coastguard Worker 
112*fd525a9cSAndroid Build Coastguard Worker   for (int i = 0; i < doc.misk1_size(); ++i) ToXml(doc.misk1(i));
113*fd525a9cSAndroid Build Coastguard Worker   if (doc.has_doctype()) ToXml(doc.doctype());
114*fd525a9cSAndroid Build Coastguard Worker   ToXml(doc.element());
115*fd525a9cSAndroid Build Coastguard Worker   for (int i = 0; i < doc.misk2_size(); ++i) ToXml(doc.misk2(i));
116*fd525a9cSAndroid Build Coastguard Worker 
117*fd525a9cSAndroid Build Coastguard Worker   return out_.str();
118*fd525a9cSAndroid Build Coastguard Worker }
119*fd525a9cSAndroid Build Coastguard Worker 
120*fd525a9cSAndroid Build Coastguard Worker }  // namespace
121*fd525a9cSAndroid Build Coastguard Worker 
MessageToXml(const Document & document)122*fd525a9cSAndroid Build Coastguard Worker std::string MessageToXml(const Document& document) {
123*fd525a9cSAndroid Build Coastguard Worker   XmlWriter writer;
124*fd525a9cSAndroid Build Coastguard Worker   return writer.ToXml(document);
125*fd525a9cSAndroid Build Coastguard Worker }
126*fd525a9cSAndroid Build Coastguard Worker 
127*fd525a9cSAndroid Build Coastguard Worker }  // namespace xml
128*fd525a9cSAndroid Build Coastguard Worker }  // namespace protobuf_mutator
129