void SVGAnalyzer::on_exit_element() { m_elements_in_process.pop_back(); }
+SVG::SVGElement &SVGAnalyzer::parent_element() {
+ if (m_elements_in_process.empty()) {
+ throw std::runtime_error{"No current element to get parent of"};
+ }
+ if (m_elements_in_process.size() == 1) {
+ throw std::runtime_error{"No parent element"};
+ }
+ return *m_elements_in_process.end()[-2];
+}
+
SVG::SVGElement &SVGAnalyzer::current_element() {
if (m_elements_in_process.empty()) {
throw std::runtime_error{"No current element"};
void SVGAnalyzer::set_text(std::string_view text) {
auto &element = current_element();
element.text = text;
+
+ if (element.type == SVG::SVGElementType::Title) {
+ // The title text is normally the 'graph_id', 'node_id' or 'edgeop'
+ // according to the DOT language specification. Save it on the parent 'g'
+ // element to avoid having to look it up later.
+ if (parent_element().type != SVG::SVGElementType::Group) {
+ throw std::runtime_error{"Unexpected parent element of 'title' element"};
+ }
+ parent_element().graphviz_id = text;
+ }
}
void SVGAnalyzer::set_graphviz_version(std::string_view version) {
/// Enter a new SVG element retrieved by the SVG document traverser into the
/// list of elements currently being processed
void enter_element(SVG::SVGElementType type);
+ /// Get the parent element of the current element being processed by the SVG
+ /// document traverser
+ SVG::SVGElement &parent_element();
/// A list of pointers to elements currently being processed by the SVG++
/// document traverser, in hierarchical order. The front element is the top
/// The Graphviz build date
std::string graphviz_build_date;
std::vector<SVGElement> children;
+ /// The `graph_id`, `node_id` or `edgeop` according to the DOT language
+ /// specification. Note that this is not the same as the `id` attribute of the
+ /// SVG element
+ std::string graphviz_id;
/// The Graphviz release version
std::string graphviz_version;
/// The SVG element text node contents. Not to be confused with an SVG `text`