47 const string doctype(
"<?xml version='1.0' encoding='ISO-8859-1'?>");
54 void output_field(
const XmlElement& xf,
const int depth, ostream& outf,
const string& compon=
string(),
bool required=
true);
58 ostream& outf,
const string& compon=
string(),
bool required=
true);
60 ostream& outf,
bool required=
true);
62 ostream& outf,
const string& compon=
string(),
bool required=
true);
75 xf.
find(
"fix/fields/field", fldlist);
78 xf.
find(
"fix/components/component", comlist);
83 xf.
find(
"fix/messages/message", msglist);
86 outf <<
'<' << xf.
GetTag();
90 const XmlElement *header(xf.find("fix/header"));
92 process_messages(*header, components, "header", 0, outf);
93 const XmlElement *trailer(xf.find("fix/trailer"));
95 process_messages(*trailer, components, "trailer", 0, outf);
97 outf << string(depth * 2, ' ') << "<messages>" << endl;
98 for(auto const *pp : msglist)
99 process_messages(*pp, components, "message", depth, outf);
100 outf << string(depth * 2, ' ') << "</messages>" << endl;
102 process_fields(fldlist, depth, outf);
104 dump_components(components, outf);
106 outf << "</" << xf.GetTag() << '>
' << endl;
111 //-----------------------------------------------------------------------------------------
112 int precompfixt(XmlElement& xft, XmlElement& xf, ostream& outf, bool nounique)
115 XmlElement::XmlSet fldlist;
116 xft.find("fix/fields/field", fldlist);
117 xf.find("fix/fields/field", fldlist);
119 filter_unique(fldlist);
121 XmlElement::XmlSet comlist, comlistfixt;
122 Components components, componentsfixt;
123 xft.find("fix/components/component", comlistfixt);
124 xf.find("fix/components/component", comlist);
125 load_components(comlistfixt, componentsfixt);
126 load_components(comlist, components);
128 outf << doctype << endl;
129 outf << '<
' << xft.GetTag();
130 output_attributes(xft, outf);
133 const XmlElement *header(xft.find("fix/header"));
135 process_messages(*header, componentsfixt, "header", 0, outf);
136 const XmlElement *trailer(xft.find("fix/trailer"));
138 process_messages(*trailer, componentsfixt, "trailer", 0, outf);
140 outf << string(depth * 2, ' ') << "<messages>" << endl;
142 XmlElement::XmlSet msglist;
143 xft.find("fix/messages/message", msglist);
144 for(auto const *pp : msglist)
145 process_messages(*pp, componentsfixt, "message", depth, outf);
148 xf.find("fix/messages/message", msglist);
149 for(auto const *pp : msglist)
150 process_messages(*pp, components, "message", depth, outf);
151 outf << string(depth * 2, ' ') << "</messages>" << endl;
153 process_fields(fldlist, depth, outf);
155 dump_components(components, outf);
157 outf << "</" << xft.GetTag() << '>
' << endl;
162 //-----------------------------------------------------------------------------------------
163 void filter_unique(XmlElement::XmlSet& fldlist)
165 using UniqueFieldMap = map<string, const XmlElement *>;
168 for(const auto *pp : fldlist)
171 pp->GetAttr("name", name);
172 if (!ufm.insert({name, pp}).second)
173 ++dupls; // cerr << "Duplicate field: " << name << endl;
177 for(const auto& pp : ufm)
178 fldlist.insert(pp.second);
181 //-----------------------------------------------------------------------------------------
182 void load_components(const XmlElement::XmlSet& comlist, Components& components)
184 for(const auto *pp : comlist)
187 if (pp->GetAttr("name", name))
188 components.insert({name, pp});
192 //-----------------------------------------------------------------------------------------
193 void process_fields(const XmlElement::XmlSet& fldlist, const int depth, ostream& outf, bool required)
195 outf << string(depth * 2, ' ') << "<fields>" << endl;
196 for(XmlElement::XmlSet::const_iterator itr(fldlist.begin()); itr != fldlist.end(); ++itr)
198 outf << string((depth + 1) * 2, ' ') << "<field";
199 output_attributes(**itr, outf, required);
201 if ((*itr)->GetChildCnt())
204 for(XmlElement::XmlSet::const_iterator fitr((*itr)->begin()); fitr != (*itr)->end(); ++fitr)
206 outf << string((depth + 2) * 2, ' ') << '<
' << (*fitr)->GetTag();
207 output_attributes(**fitr, outf, required);
208 outf << "/>" << endl;
210 outf << string((depth + 1) * 2, ' ') << "</field>" << endl;
213 outf << "/>" << endl;
215 outf << string(depth * 2, ' ') << "</fields>" << endl;
218 //-----------------------------------------------------------------------------------------
219 void output_field(const XmlElement& xf, const int depth, ostream& outf, const string& compon, bool required)
221 outf << string(depth * 2, ' ') << "<field";
222 output_attributes(xf, outf, required);
224 outf << " component=\'" << compon << '\
'';
225 outf <<
"/>" << endl;
231 for (XmlElement::XmlAttrs::const_iterator itr(xf.
abegin()); itr != xf.
aend(); ++itr)
232 outf <<
' ' << itr->first <<
"='"
233 << (itr->first ==
"required" && itr->second ==
"Y" && !required ?
"N" : itr->second) <<
'\'';
235 outf <<
" line=\'" << xf.
GetLine() <<
'\'';
240 ostream& outf,
const string& compon,
bool required)
242 if ((*itr)->GetTag() ==
"field")
244 else if ((*itr)->GetTag() ==
"component")
246 else if ((*itr)->GetTag() ==
"group")
247 process_group(**itr, components, depth, outf, compon, required);
253 outf << string((depth + 1) * 2,
' ') <<
'<' << tag;
257 for(XmlElement::XmlSet::const_iterator mitr(xf.begin()); mitr != xf.end(); ++mitr)
258 process_elements(mitr, components, depth + 2, outf, string(), required);
259 outf << string((depth + 1) * 2, ' ') << "</" << tag << '>
' << endl;
262 //-----------------------------------------------------------------------------------------
263 void process_component(const XmlElement& xf, const Components& components, const int depth, ostream& outf, bool required)
266 xf.GetAttr("name", name);
267 bool comp_required(xf.FindAttr("required", false));
269 Components::const_iterator citr(components.find(name));
270 if (citr == components.end())
272 cerr << shortName << ':
' << recover_line(xf) << ": error: Could not find component '" << name << '\'' << endl;
277 for(XmlElement::XmlSet::const_iterator itr(citr->second->begin()); itr != citr->second->end(); ++itr)
278 process_elements(itr, components, depth, outf, name,
279 depth == 3 ? comp_required : comp_required && required);
283 //-----------------------------------------------------------------------------------------
284 void process_group(const XmlElement& xf, const Components& components, const int depth,
285 ostream& outf, const string& compon, bool required)
287 outf << string(depth * 2, ' ') << "<group
";
288 output_attributes(xf, outf, required);
290 outf << " component=\
'" << compon << '\
'';
293 for(XmlElement::XmlSet::const_iterator itr(xf.begin()); itr != xf.end(); ++itr)
294 process_elements(itr, components, depth + 1, outf, string(), required);
295 outf << string(depth * 2, ' ') << "</group>" << endl;
298 //-----------------------------------------------------------------------------------------
299 void dump_components(const Components& components, ostream& outf)
301 if (components.empty())
306 outf << string(depth * 2, ' ') << "<components>" << endl;
308 for (Components::const_iterator citr(components.begin()); citr != components.end(); ++citr)
310 outf << string((depth + 1) * 2, ' ') << "<component name=\"";
311 outf << citr->first << "\" id=\"" << (1 + distance(components.begin(), citr)) << "\"/>" << endl;
314 outf << string(depth * 2, ' ') << "</components>" << endl;
void dump_components(const Components &components, ostream &outf)
void process_group(const XmlElement &xf, const Components &components, const int depth, ostream &outf, const string &compon=string(), bool required=true)
void filter_unique(XmlElement::XmlSet &fldlist)
void output_attributes(const XmlElement &xf, ostream &outf, bool required=true)
std::map< std::string, const XmlElement * > Components
void process_elements(XmlElement::XmlSet::const_iterator itr, const Components &components, const int depth, ostream &outf, const string &compon=string(), bool required=true)
void process_messages(const XmlElement &xf, const Components &components, const string &tag, const int depth, ostream &outf, bool required=true)
int precomp(XmlElement &xf, ostream &outf)
void load_components(const XmlElement::XmlSet &comlist, Components &components)
void process_component(const XmlElement &xf, const Components &components, const int depth, ostream &outf, bool required=true)
A simple xml parser with Xpath style lookup.
XmlAttrs::const_iterator abegin() const
void output_field(const XmlElement &xf, const int depth, ostream &outf, const string &compon=string(), bool required=true)
void process_fields(const XmlElement::XmlSet &fldlist, const int depth, ostream &outf, bool required=true)
std::set< const XmlElement *, EntityOrderComp > XmlSet
XmlAttrs::const_iterator aend() const
const std::string & GetTag() const
const string doctype("<?xml version='1.0' encoding='ISO-8859-1'?>")
int precompfixt(XmlElement &xft, XmlElement &xf, ostream &outf, bool nounique)
F8API const XmlElement * find(const std::string &what, const std::string *atag=nullptr, const std::string *aval=nullptr, const char delim='/') const