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