📄 svgparser.cc
字号:
// -*- C++ -*-/* svgparser.cc * * By Dan Dennedy <dan@dennedy.org> * * Copyright (C) 2003 The libxml++ development team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <iostream>#include <libxml/tree.h>#include "svgparser.h"#include "svgdocument.h"#include "svgelement.h"#include "svgpath.h"#include "svggroup.h"namespace SVG {Parser::Parser(xmlpp::Document& document) : xmlpp::SaxParser(true), m_doc(document){ set_substitute_entities(true);}Parser::~Parser(){}void Parser::on_start_element(const std::string& name, const AttributeList& attributes){ //This method replaces the normal libxml++ node //with an instance of a derived node. //This is not a recommended technique, and might not //work with future versions of libxml++. // Parse namespace prefix and save for later: std::string elementPrefix; std::string elementName = name; std::string::size_type idx = name.find(':'); if (idx != std::string::npos) //If the separator was found { elementPrefix = name.substr(0, idx); elementName = name.substr(idx + 1); } xmlpp::Element* element_normal = 0; // Create a normal libxml++ node: if (m_doc.get_root_node() == 0) { // Create the root node if necessary: element_normal = m_doc.create_root_node(elementName); } else { // Create the other elements as child nodes of the last nodes: element_normal = m_context.top()->add_child(elementName); } // TODO: The following is a hack because it leverages knowledge of libxml++ // implementation rather than interface - specifically that deleting the C++ // instance will leave the underlying C instance intact and part of the libxml DOM tree. // // Delete the xmlpp::Element created above so we can link the libxml2 // node with the derived Element object we create below. xmlNode* node = element_normal->cobj(); //Save it for later. delete element_normal; element_normal = 0; // TODO: Again, this requires knowledge of the libxml++ implemenation - // specifically that the base xmlpp::Node() constructor will reassociate // the underyling C instance with this new C++ instance, by seeting _private. // // Construct a custom Element based upon prefix and name. // This will then be deleted by libxml++, just as libxml++ would normally have // deleted its own node. // TODO: Don't delete the original (above) if it isn't one of these node names. xmlpp::Element* element_derived = 0; if (elementName == "g") element_derived = new SVG::Group(node); else if (elementName == "path") element_derived = new SVG::Path(node); else element_derived = new SVG::Element(node); if(element_derived) { //Set the context, so that child nodes will be added to this node, //until on_end_element(): m_context.push(element_derived); // Copy the attributes form the old node to the new derived node: // In theory, you could change the attributes here. for(xmlpp::SaxParser::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { std::string name = (*iter).name; std::string value = (*iter).value; std::string::size_type idx = name.find(':'); if (idx == std::string::npos) // If the separator was not found. { if (name == "xmlns") // This is a namespace declaration. { //There is no second part, so this is a default namespace declaration. element_derived->set_namespace_declaration(value); } else { //This is just an attribute value: element_derived->set_attribute(name, value); } } else { //The separator was found: std::string prefix = name.substr(0, idx); std::string suffix = name.substr(idx + 1); if (prefix == "xmlns") // This is a namespace declaration. element_derived->set_namespace_declaration(value, suffix); else { //This is a namespaced attribute value. //(The namespace must have been declared already) xmlpp::Attribute* attr = element_derived->set_attribute(suffix, value); attr->set_namespace(prefix); //alternatively, we could have specified the whole name to set_attribute(). } } } // We have to set the element namespace after the attributes because // an attribute might declare the namespace used in the actual element's name. if (!elementPrefix.empty()) element_derived->set_namespace(elementPrefix); }}void Parser::on_end_element(const std::string& name){ // This causes the next child elements to be added to the sibling, not this node. m_context.pop();}void Parser::on_characters(const std::string& text){ if (m_context.size()) m_context.top()->add_child_text(text);}void Parser::on_comment(const std::string& text){ if (m_context.size()) m_context.top()->add_child_comment(text); else m_doc.add_comment(text);}void Parser::on_warning(const std::string& text){ std::cout << "on_warning(): " << text << std::endl;}void Parser::on_error(const std::string& text){ std::cout << "on_error(): " << text << std::endl;}void Parser::on_fatal_error(const std::string& text){ std::cout << "on_fatal_error(): " << text << std::endl;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -