Bitstream Interpretation Library (BIL)  0.1
XMLWriter.cpp
Go to the documentation of this file.
1 
6 #include <util/XMLWriter.hpp>
7 
8 using namespace bil;
9 
10 
11 const char OPENINGTAG_START = '<';
12 const char OPENINGTAG_ENDEMPTY[] = " />";
13 const char TAG_END = '>';
14 const char CLOSINGTAG_START[] = "</";
15 
16 const char ATTRIB_START[] = "=\"";
17 const char ATTRIB_END[] = "\"";
18 
19 const char PINST_START[] = "<?";
20 const char PINST_END[] = "?>";
21 
22 const char INDENT_CHAR = ' ';
23 
24 
25 XMLWriter::XMLWriter(std::ostream& os, size_t baseIndent, size_t levelIndent):
26  m_outputStream(os),
27  m_elementStack(),
28  m_insideOpeningTag(false),
29  m_lineIndentString(baseIndent, INDENT_CHAR),
30  m_levelIndent(levelIndent)
31 {
32  // write out first indent without line break
33  m_outputStream << m_lineIndentString;
34  // then add line break to indent string
35  m_lineIndentString.insert(0, 1, '\n');
36 }
37 
38 
39 void XMLWriter::beginElement(const std::string& name, bool newLine)
40 {
41  // finish an eventually unfinished opening tag
42  if (m_insideOpeningTag) m_outputStream << TAG_END;
43 
44  // if new line is wanted write line break and indent
45  if (newLine) m_outputStream << m_lineIndentString;
46 
47  // write tag and push tag name onto stack
48  m_outputStream << OPENINGTAG_START << name;
49  m_elementStack.push(name);
50  // set inside opening tag flag
51  m_insideOpeningTag = true;
52 
53  // update indent string: add indent for opening level
54  m_lineIndentString.append(m_levelIndent, INDENT_CHAR);
55 }
56 
57 
58 void XMLWriter::endElement(bool newLine)
59 {
60  // throw if no element is open
61  if (0 >= m_elementStack.size()) throw ;
62 
63  // update indent string: remove indent for closing level
64  m_lineIndentString.resize(m_lineIndentString.size() - m_levelIndent);
65 
66  // Test if a full closing element is necessary: If not, mark opening element
67  // as empty; else write full closing element.
68  if (m_insideOpeningTag) m_outputStream << OPENINGTAG_ENDEMPTY;
69  else
70  {
71  // if new line is wanted write line break and indent
72  if (newLine) m_outputStream << m_lineIndentString;
73  m_outputStream << CLOSINGTAG_START << m_elementStack.top() << TAG_END;
74  }
75 
76  // remove tag name from stack
77  m_elementStack.pop();
78 
79  // clear inside opening tag flag
80  m_insideOpeningTag = false;
81 }
82 
83 
84 void XMLWriter::addAttribute(const std::string& name, const std::string& value)
85 {
86  // test if attribute can now be written (must be inside an opening tag) and
87  // write it
88  if (!m_insideOpeningTag) throw ;
89  m_outputStream << ' ' << name << ATTRIB_START << value << ATTRIB_END;
90 }
91 
92 
93 void XMLWriter::addAttribute(const std::string& name, unsigned value)
94 {
95  // test if attribute can now be written (must be inside an opening tag) and
96  // write it
97  if (!m_insideOpeningTag) throw ;
98  m_outputStream << ' ' << name << ATTRIB_START << value << ATTRIB_END;
99 }
100 
101 
102 void XMLWriter::addData(const std::string& data, bool newLine)
103 {
104  // finish an eventually unfinished opening tag
105  if (m_insideOpeningTag) m_outputStream << TAG_END;
106  m_insideOpeningTag = false;
107 
108  // if new line is wanted write line break and indent
109  if (newLine) m_outputStream << m_lineIndentString;
110 
111  // write data
112  m_outputStream << data;
113 }
114 
115 
116 void XMLWriter::addProcessingInstruction(const std::string& target, const std::string& instruction, bool newLine)
117 {
118  // finish an eventually unfinished opening tag
119  if (m_insideOpeningTag) m_outputStream << TAG_END;
120  m_insideOpeningTag = false;
121 
122  // if new line is wanted write line break and indent
123  if (newLine) m_outputStream << m_lineIndentString;
124 
125  // write PI
126  m_outputStream << PINST_START << target << ' ' << instruction << PINST_END;
127 }
128 
129 
130 size_t XMLWriter::depth() const
131 {
132  return m_elementStack.size();
133 }
134 
135 
136 std::string XMLWriter::element() const
137 {
138  return m_elementStack.top();
139 }