Create new element to insert custom strings when generating XMLs
Closed this issue · 8 comments
Add a new element whose sole purpose is to insert custom strings when generating XMLs. This new element could be called StringElement
.
You can create such element by just deriving from svgdom::Element
. What needs to be done is to expose the StringWriter visitor class, so that it is also possible to extend it.
@JaimeIvanCervantes what is you exact problem, i.e. what do you want to achieve here? Is it writing the SVG which contains custom elements to string?
I just submitted a PR with my solution: #10
What I want to do is very simple, I just want to insert any text to the XML string. I need this to insert code for custom elements that are not found in the SVG spec. I created an Element called CustomStringElement
(in files Custom.hpp
and Custom.cpp
). Here's an example:
auto dom = utki::makeUnique<svgdom::SvgElement>();
svgdom::PathElement path;
svgdom::PathElement::Step step;
step.type = svgdom::PathElement::Step::Type_e::MOVE_ABS;
step.x = 0;
step.y = 0;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 0;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 0;
path.path.push_back(step);
dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path));
svgdom::CustomStringElement custom("Any string goes here.");
dom->children.push_back(utki::makeUnique<svgdom::CustomStringElement>(custom));
cout<<dom->toString()<<std::endl;
The line custom.setCustomString("Any string goes here.")
inserts a string in the XML. Here's the output:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<path d="M0,0L0,300 300,300 300,0"/>
Any string goes here.
</svg>
I wrote this out of pure necessity, and I tried to use your code conventions, but feel free to add or rename anything you want.
I made changes to support custom elements. I refactored the StreamWriter so that it now allows writing of custom elements and adding even custom attributes to standard elements.
I added a test cases which demonstrates how to achieve that: https://github.com/igagis/svgdom/blob/master/tests/customElement/main.cpp
The svgdom version 0.2.61 should be available within an hour. Please check if it suits your needs.
I updated the https://github.com/igagis/svgdom/blob/master/tests/customElement/main.cpp test a bit.
Unfortunately my project requires me to insert strings that are not necessarily svg elements or attributes. I know that this might not be a usual case, so I decided to use the following code to create my custom element:
struct CustomElement : public svgdom::Element{
std::string str;
CustomElement(std::string s) : str(s) {}
void accept(svgdom::Visitor& visitor) const override;
};
class CustomStreamWriter : public svgdom::StreamWriter{
public:
CustomStreamWriter(std::ostream& s) :
svgdom::StreamWriter(s)
{}
using svgdom::StreamWriter::visit;
virtual void visit(const CustomElement& e){
auto ind = indentStr();
this->s << ind;
this->s << e.str;
this->s << std::endl;
}
};
void CustomElement::accept(svgdom::Visitor& visitor) const{
if(auto v = dynamic_cast<CustomStreamWriter*>(&visitor)){
v->visit(*this);
}else{
visitor.defaultVisit(*this);
}
}
int main(int argc, char** argv) {
auto dom = utki::makeUnique<svgdom::SvgElement>();
svgdom::PathElement path;
svgdom::PathElement::Step step;
step.type = svgdom::PathElement::Step::Type_e::MOVE_ABS;
step.x = 0;
step.y = 0;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 0;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 0;
path.path.push_back(step);
dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path));
dom->children.push_back(utki::makeUnique<CustomElement>("Any string goes here."));
std::stringstream ss;
CustomStreamWriter writer(ss);
dom->accept(writer);
auto str = ss.str();
cout<<str<<endl;
}
This will produce the following output:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<path d="M0,0 L0,300 300,300 300,0"/>
Any string goes here.
</svg>
In order for my custom element to work though, I would need to merge the following PR where I am only moving s
, indentStr()
, and indent
members from private
to protected
: #11
This is really important for my project :).
The PR seems OK, but I asked you to add a comment there. Please also check the updated test https://github.com/igagis/svgdom/blob/master/tests/customElement/main.cpp and update your code accordingly, because it is not very good to cast to CustomStreamWriter
in the accept
method.
PR merged